Fix concurrency on the client (#183)

* reworked peer connection establishment logic eliminating race conditions and deadlocks while running many peers
This commit is contained in:
Mikhail Bragin
2022-01-10 18:43:13 +01:00
committed by GitHub
parent 828410b34c
commit 319632ffe8
25 changed files with 1216 additions and 898 deletions

View File

@@ -45,6 +45,10 @@ type Client struct {
status Status
}
func (c *Client) StreamConnected() bool {
return c.status == StreamConnected
}
func (c *Client) GetStatus() Status {
return c.status
}
@@ -117,7 +121,7 @@ func (c *Client) Receive(msgHandler func(msg *proto.Message) error) error {
c.notifyStreamDisconnected()
log.Debugf("signal connection state %v", c.signalConn.GetState())
if !c.ready() {
if !c.Ready() {
return fmt.Errorf("no connection to signal")
}
@@ -204,9 +208,9 @@ func (c *Client) connect(key string) (proto.SignalExchange_ConnectStreamClient,
return stream, nil
}
// ready indicates whether the client is okay and ready to be used
// Ready indicates whether the client is okay and Ready to be used
// for now it just checks whether gRPC connection to the service is in state Ready
func (c *Client) ready() bool {
func (c *Client) Ready() bool {
return c.signalConn.GetState() == connectivity.Ready || c.signalConn.GetState() == connectivity.Idle
}
@@ -228,7 +232,7 @@ func (c *Client) WaitStreamConnected() {
// The Client.Receive method must be called before sending messages to establish initial connection to the Signal Exchange
// Client.connWg can be used to wait
func (c *Client) SendToStream(msg *proto.EncryptedMessage) error {
if !c.ready() {
if !c.Ready() {
return fmt.Errorf("no connection to signal")
}
if c.stream == nil {
@@ -287,7 +291,7 @@ func (c *Client) encryptMessage(msg *proto.Message) (*proto.EncryptedMessage, er
// Send sends a message to the remote Peer through the Signal Exchange.
func (c *Client) Send(msg *proto.Message) error {
if !c.ready() {
if !c.Ready() {
return fmt.Errorf("no connection to signal")
}
@@ -295,9 +299,11 @@ func (c *Client) Send(msg *proto.Message) error {
if err != nil {
return err
}
_, err = c.realClient.Send(context.TODO(), encryptedMessage)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, err = c.realClient.Send(ctx, encryptedMessage)
if err != nil {
//log.Errorf("error while sending message to peer [%s] [error: %v]", msg.RemoteKey, err)
return err
}