Merge pull request #161 from remicorniere/Issue_160

Fix issue #160
This commit is contained in:
remicorniere 2020-03-16 22:29:03 +00:00 committed by GitHub
commit fe4c366de8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 8 deletions

View file

@ -42,12 +42,12 @@ func (scs *SyncConnState) setState(cs ConnState) {
// This is a the list of events happening on the connection that the // This is a the list of events happening on the connection that the
// client can be notified about. // client can be notified about.
const ( const (
InitialPresence = "<presence/>"
StateDisconnected ConnState = iota StateDisconnected ConnState = iota
StateResuming StateResuming
StateSessionEstablished StateSessionEstablished
StateStreamError StateStreamError
StatePermanentError StatePermanentError
InitialPresence = "<presence/>"
) )
// Event is a structure use to convey event changes related to client state. This // 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 { if err != nil {
return err 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. // for example.
if c.PostResumeHook != nil { if c.PostResumeHook != nil {
err = c.PostResumeHook() err = c.PostResumeHook()

View file

@ -80,13 +80,13 @@ func (sm *StreamManager) Run() error {
sm.Metrics.setLoginTime() sm.Metrics.setLoginTime()
case StateDisconnected: case StateDisconnected:
// Reconnect on disconnection // Reconnect on disconnection
return sm.resume(e.SMState) return sm.resume()
case StateStreamError: case StateStreamError:
sm.client.Disconnect() sm.client.Disconnect()
// Only try reconnecting if we have not been kicked by another session to avoid connection loop. // Only try reconnecting if we have not been kicked by another session to avoid connection loop.
// TODO: Make this conflict exception a permanent error // TODO: Make this conflict exception a permanent error
if e.StreamError != "conflict" { if e.StreamError != "conflict" {
return sm.connect() return sm.resume()
} }
case StatePermanentError: case StatePermanentError:
// Do not attempt to reconnect // Do not attempt to reconnect
@ -113,19 +113,32 @@ func (sm *StreamManager) Stop() {
} }
func (sm *StreamManager) connect() error { func (sm *StreamManager) connect() error {
var state SMState if sm.client != nil {
return sm.resume(state) 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. // 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? var backoff backoff // TODO: Group backoff calculation features with connection manager?
for { for {
var err error var err error
// TODO: Make it possible to define logger to log disconnect and reconnection attempts // TODO: Make it possible to define logger to log disconnect and reconnection attempts
sm.Metrics = initMetrics() sm.Metrics = initMetrics()
if err = sm.client.Resume(); err != nil { if err = sm.client.Resume(); err != nil {
var actualErr ConnError var actualErr ConnError
if xerrors.As(err, &actualErr) { if xerrors.As(err, &actualErr) {