~rjarry/aerc

beae17a6da37402d1c69dc76b476f55cbae982b8 — Koni Marti 4 months ago 1ace50a
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>
3 files changed, 30 insertions(+), 3 deletions(-)

M widgets/account.go
M worker/imap/worker.go
M worker/types/messages.go
M widgets/account.go => widgets/account.go +2 -1
@@ 202,7 202,7 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
	switch msg := msg.(type) {
	case *types.Done:
		switch msg.InResponseTo().(type) {
		case *types.Connect:
		case *types.Connect, *types.Reconnect:
			acct.host.SetStatus("Listing mailboxes...")
			acct.logger.Println("Listing mailboxes...")
			acct.dirlist.UpdateList(func(dirs []string) {


@@ 291,6 291,7 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
	case *types.ConnError:
		acct.logger.Printf("Connection error = %v", msg.Error)
		acct.aerc.PushError(fmt.Sprintf("%v", msg.Error))
		acct.worker.PostAction(&types.Reconnect{}, nil)
	case *types.Error:
		acct.logger.Printf("%v", msg.Error)
		acct.aerc.PushError(fmt.Sprintf("%v", msg.Error))

M worker/imap/worker.go => worker/imap/worker.go +24 -2
@@ 55,8 55,9 @@ type IMAPWorker struct {
	updates  chan client.Update
	worker   *types.Worker
	// Map of sequence numbers to UIDs, index 0 is seq number 1
	seqMap []uint32
	done   chan struct{}
	seqMap        []uint32
	done          chan struct{}
	autoReconnect bool
}

func NewIMAPWorker(worker *types.Worker) (types.Backend, error) {


@@ 186,6 187,26 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {

		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)
	case *types.Disconnect:
		if w.client == nil || w.client.State() != imap.SelectedState {


@@ 199,6 220,7 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
			reterr = err
			break
		}
		w.autoReconnect = false
		w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
	case *types.ListDirectories:
		w.handleListDirectories(msg)

M worker/types/messages.go => worker/types/messages.go +4 -0
@@ 68,6 68,10 @@ type Connect struct {
	Message
}

type Reconnect struct {
	Message
}

type Disconnect struct {
	Message
}