imap: improve reconnect stability
improves the robustness of the imap reconnect feature which was
introduced in commit beae17a6da
("imap: auto-reconnects on connection
error").
If a connection error is emitted, the message list is cleared and a
corresponding error message is shown in the ui. Status bar is updated as
well. Upon reconnect, the directories and the message list will be
re-fetched (same behavior as the connect command).
Reconnect can be enabled and disabled with the connect and the
disconnect commands.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
This commit is contained in:
parent
4bd4f4664a
commit
05ad96a30c
2 changed files with 22 additions and 8 deletions
|
@ -289,8 +289,10 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
|
||||||
case *types.LabelList:
|
case *types.LabelList:
|
||||||
acct.labels = msg.Labels
|
acct.labels = msg.Labels
|
||||||
case *types.ConnError:
|
case *types.ConnError:
|
||||||
acct.logger.Printf("Connection error = %v", msg.Error)
|
acct.logger.Printf("connection error: %v", msg.Error)
|
||||||
|
acct.host.SetStatus("Disconnected.")
|
||||||
acct.aerc.PushError(fmt.Sprintf("%v", msg.Error))
|
acct.aerc.PushError(fmt.Sprintf("%v", msg.Error))
|
||||||
|
acct.msglist.SetStore(nil)
|
||||||
acct.worker.PostAction(&types.Reconnect{}, nil)
|
acct.worker.PostAction(&types.Reconnect{}, nil)
|
||||||
case *types.Error:
|
case *types.Error:
|
||||||
acct.logger.Printf("%v", msg.Error)
|
acct.logger.Printf("%v", msg.Error)
|
||||||
|
|
|
@ -85,6 +85,11 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
checkConn := func() {
|
||||||
|
w.stopConnectionObserver()
|
||||||
|
w.startConnectionObserver()
|
||||||
|
}
|
||||||
|
|
||||||
var reterr error // will be returned at the end, needed to support idle
|
var reterr error // will be returned at the end, needed to support idle
|
||||||
|
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
|
@ -171,9 +176,15 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
}
|
}
|
||||||
case *types.Connect:
|
case *types.Connect:
|
||||||
if w.client != nil && w.client.State() == imap.SelectedState {
|
if w.client != nil && w.client.State() == imap.SelectedState {
|
||||||
|
if !w.autoReconnect {
|
||||||
|
w.autoReconnect = true
|
||||||
|
checkConn()
|
||||||
|
}
|
||||||
reterr = fmt.Errorf("Already connected")
|
reterr = fmt.Errorf("Already connected")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.autoReconnect = true
|
||||||
c, err := w.connect()
|
c, err := w.connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reterr = err
|
reterr = err
|
||||||
|
@ -187,7 +198,6 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
|
|
||||||
w.startConnectionObserver()
|
w.startConnectionObserver()
|
||||||
|
|
||||||
w.autoReconnect = true
|
|
||||||
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
|
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
|
||||||
case *types.Reconnect:
|
case *types.Reconnect:
|
||||||
if !w.autoReconnect {
|
if !w.autoReconnect {
|
||||||
|
@ -196,6 +206,7 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
}
|
}
|
||||||
c, err := w.connect()
|
c, err := w.connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
checkConn()
|
||||||
reterr = err
|
reterr = err
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -209,18 +220,17 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
|
|
||||||
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
|
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
|
||||||
case *types.Disconnect:
|
case *types.Disconnect:
|
||||||
|
w.autoReconnect = false
|
||||||
|
w.stopConnectionObserver()
|
||||||
if w.client == nil || w.client.State() != imap.SelectedState {
|
if w.client == nil || w.client.State() != imap.SelectedState {
|
||||||
reterr = fmt.Errorf("Not connected")
|
reterr = fmt.Errorf("Not connected")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
w.stopConnectionObserver()
|
|
||||||
|
|
||||||
if err := w.client.Logout(); err != nil {
|
if err := w.client.Logout(); err != nil {
|
||||||
reterr = err
|
reterr = err
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
w.autoReconnect = false
|
|
||||||
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
|
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
|
||||||
case *types.ListDirectories:
|
case *types.ListDirectories:
|
||||||
w.handleListDirectories(msg)
|
w.handleListDirectories(msg)
|
||||||
|
@ -306,9 +316,11 @@ func (w *IMAPWorker) startConnectionObserver() {
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
select {
|
||||||
case <-w.client.LoggedOut():
|
case <-w.client.LoggedOut():
|
||||||
|
if w.autoReconnect {
|
||||||
w.worker.PostMessage(&types.ConnError{
|
w.worker.PostMessage(&types.ConnError{
|
||||||
Error: fmt.Errorf("Logged Out"),
|
Error: fmt.Errorf("imap: logged out"),
|
||||||
}, nil)
|
}, nil)
|
||||||
|
}
|
||||||
case <-w.done:
|
case <-w.done:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue