From 0a4acd12c34b0048ff7554b7c56ddce975eb9286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?CORNIERE=20R=C3=A9mi?= Date: Mon, 16 Mar 2020 16:20:54 +0100 Subject: [PATCH] Fix issue #160 --- client.go | 4 ++-- stream_manager.go | 25 +++++++++++++++++++------ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/client.go b/client.go index 7613af4..9969472 100644 --- a/client.go +++ b/client.go @@ -42,12 +42,12 @@ func (scs *SyncConnState) setState(cs ConnState) { // This is a the list of events happening on the connection that the // client can be notified about. const ( - InitialPresence = "" StateDisconnected ConnState = iota StateResuming StateSessionEstablished StateStreamError StatePermanentError + InitialPresence = "" ) // Event is a structure use to convey event changes related to client state. This @@ -285,7 +285,7 @@ func (c *Client) Resume() error { if err != nil { return err } - // Execute post reconnect hook. This can be different from the first connection hook, and not trigger roster retrival + // Execute post reconnect hook. This can be different from the first connection hook, and not trigger roster retrieval // for example. if c.PostResumeHook != nil { err = c.PostResumeHook() diff --git a/stream_manager.go b/stream_manager.go index da23df1..7bfb42c 100644 --- a/stream_manager.go +++ b/stream_manager.go @@ -80,13 +80,13 @@ func (sm *StreamManager) Run() error { sm.Metrics.setLoginTime() case StateDisconnected: // Reconnect on disconnection - return sm.resume(e.SMState) + return sm.resume() case StateStreamError: sm.client.Disconnect() // Only try reconnecting if we have not been kicked by another session to avoid connection loop. // TODO: Make this conflict exception a permanent error if e.StreamError != "conflict" { - return sm.connect() + return sm.resume() } case StatePermanentError: // Do not attempt to reconnect @@ -113,19 +113,32 @@ func (sm *StreamManager) Stop() { } func (sm *StreamManager) connect() error { - var state SMState - return sm.resume(state) + if sm.client != nil { + if c, ok := sm.client.(*Client); ok { + if c.CurrentState.getState() == StateDisconnected { + sm.Metrics = initMetrics() + err := c.Connect() + if err != nil { + return err + } + if sm.PostConnect != nil { + sm.PostConnect(sm.client) + } + return nil + } + } + } + return errors.New("client is not disconnected") } // resume manages the reconnection loop and apply the define backoff to avoid overloading the server. -func (sm *StreamManager) resume(state SMState) error { +func (sm *StreamManager) resume() error { var backoff backoff // TODO: Group backoff calculation features with connection manager? for { var err error // TODO: Make it possible to define logger to log disconnect and reconnection attempts sm.Metrics = initMetrics() - if err = sm.client.Resume(); err != nil { var actualErr ConnError if xerrors.As(err, &actualErr) {