imap: auto-reconnects on connection error

if the worker emits a connection error, the ui will automatically send back a
reconnect command. The worker then establishes a new connection. Auto-reconnect
is disabled when the user sends the disconnect command.

Fixes: https://todo.sr.ht/~rjarry/aerc/1
Signed-off-by: Koni Marti <koni.marti@gmail.com>
This commit is contained in:
Koni Marti 2022-01-19 13:18:10 +01:00 committed by Robin Jarry
parent 1ace50a6b9
commit beae17a6da
3 changed files with 30 additions and 3 deletions

View File

@ -202,7 +202,7 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
switch msg := msg.(type) { switch msg := msg.(type) {
case *types.Done: case *types.Done:
switch msg.InResponseTo().(type) { switch msg.InResponseTo().(type) {
case *types.Connect: case *types.Connect, *types.Reconnect:
acct.host.SetStatus("Listing mailboxes...") acct.host.SetStatus("Listing mailboxes...")
acct.logger.Println("Listing mailboxes...") acct.logger.Println("Listing mailboxes...")
acct.dirlist.UpdateList(func(dirs []string) { acct.dirlist.UpdateList(func(dirs []string) {
@ -291,6 +291,7 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
case *types.ConnError: case *types.ConnError:
acct.logger.Printf("Connection error = %v", msg.Error) acct.logger.Printf("Connection error = %v", msg.Error)
acct.aerc.PushError(fmt.Sprintf("%v", msg.Error)) acct.aerc.PushError(fmt.Sprintf("%v", msg.Error))
acct.worker.PostAction(&types.Reconnect{}, nil)
case *types.Error: case *types.Error:
acct.logger.Printf("%v", msg.Error) acct.logger.Printf("%v", msg.Error)
acct.aerc.PushError(fmt.Sprintf("%v", msg.Error)) acct.aerc.PushError(fmt.Sprintf("%v", msg.Error))

View File

@ -55,8 +55,9 @@ type IMAPWorker struct {
updates chan client.Update updates chan client.Update
worker *types.Worker worker *types.Worker
// Map of sequence numbers to UIDs, index 0 is seq number 1 // Map of sequence numbers to UIDs, index 0 is seq number 1
seqMap []uint32 seqMap []uint32
done chan struct{} done chan struct{}
autoReconnect bool
} }
func NewIMAPWorker(worker *types.Worker) (types.Backend, error) { func NewIMAPWorker(worker *types.Worker) (types.Backend, error) {
@ -186,6 +187,26 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
w.startConnectionObserver() w.startConnectionObserver()
w.autoReconnect = true
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
case *types.Reconnect:
if !w.autoReconnect {
reterr = fmt.Errorf("auto-reconnect is disabled; run connect to enable it")
break
}
c, err := w.connect()
if err != nil {
reterr = err
break
}
w.stopConnectionObserver()
c.Updates = w.updates
w.client = &imapClient{c, sortthread.NewThreadClient(c), sortthread.NewSortClient(c)}
w.startConnectionObserver()
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil) w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
case *types.Disconnect: case *types.Disconnect:
if w.client == nil || w.client.State() != imap.SelectedState { if w.client == nil || w.client.State() != imap.SelectedState {
@ -199,6 +220,7 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
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)

View File

@ -68,6 +68,10 @@ type Connect struct {
Message Message
} }
type Reconnect struct {
Message
}
type Disconnect struct { type Disconnect struct {
Message Message
} }