Beispiel #1
0
func (c *clientSession) fanoutRequest(fanoutFn func(int) *fanout, cancelCh chan struct{}) interface{} {
	defer c.mutex.RUnlock()
	c.mutex.RLock()

	rpcClients := c.peerClients
	numClients := len(rpcClients)

	f := fanoutFn(numClients)

	var wg sync.WaitGroup
	wg.Add(numClients)

	doneCh := make(chan struct{})

	go func() {
		select {
		case <-cancelCh:
			f.respCh.Close()
		case <-doneCh:
			f.respCh.Close()
		}
	}()

	go func() {
		defer close(doneCh)
		wg.Wait()
	}()

	for _, r := range rpcClients {
		go func(p *peerClient) {

			// requestCh might be closed because of session being terminated
			// let go of the wait
			defer common.RecoverAndDo(func() { wg.Done() })

			p.requestCh <- func() {
				defer wg.Done()
				defer common.NoopRecoverLog() // respCh might be closed because of session being terminated

				resp, err := f.reqFn(p)
				if err != nil {
					log.Warn(err)
				} else {
					c.listener.HandleEvent(
						common.Event{
							Term:      resp.Term(),
							EventType: common.ResponseReceived,
						})

					f.respCh.Send(reflect.ValueOf(resp))
				}
			}
		}(r)
	}
	return f.respCh.Interface()
}
Beispiel #2
0
func (c *clientSession) removeGrpcClient(id string) {
	defer c.mutex.Unlock()
	defer common.NoopRecoverLog() // session is terminating and already closed requestCh and this was invoked concurrently
	c.mutex.Lock()

	if peerClient := c.peerClients[id]; peerClient != nil {
		close(peerClient.requestCh)
		delete(c.peerClients, id)
	}
}
Beispiel #3
0
func (c *clientSession) watchForTerminate() {
	defer c.mutex.RUnlock()
	defer common.NoopRecoverLog() // requestCh might be closed by an unhealthy connection in removeGrpcClient

	<-c.terminateCh

	c.mutex.RLock()

	log.Debug("Terminating session")

	for _, r := range c.peerClients {
		close(r.requestCh)
	}

	c.client.removeSession(c)
}