Handle incoming emails gracefully

This commit is contained in:
Drew DeVault 2019-05-13 20:16:55 -04:00
parent bb46b2b7e1
commit 026e8a17ca
5 changed files with 36 additions and 9 deletions

View file

@ -1,6 +1,7 @@
package lib package lib
import ( import (
"fmt"
"io" "io"
"sync" "sync"
"time" "time"
@ -140,6 +141,11 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
switch msg := msg.(type) { switch msg := msg.(type) {
case *types.DirectoryInfo: case *types.DirectoryInfo:
store.DirInfo = *msg store.DirInfo = *msg
fmt.Printf("got dirinfo, %d exists, %d known\n",
store.DirInfo.Exists, len(store.Uids))
if store.DirInfo.Exists != len(store.Uids) {
store.worker.PostAction(&types.FetchDirectoryContents{}, nil)
}
update = true update = true
case *types.DirectoryContents: case *types.DirectoryContents:
newMap := make(map[uint32]*types.MessageInfo) newMap := make(map[uint32]*types.MessageInfo)

View file

@ -161,17 +161,17 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
} else { } else {
acct.msglist.SetStore(nil) acct.msglist.SetStore(nil)
} }
acct.worker.PostAction(&types.FetchDirectoryContents{},
func(msg types.WorkerMessage) {
store := acct.msgStores[acct.dirlist.selected]
acct.msglist.SetStore(store)
})
} }
case *types.DirectoryInfo: case *types.DirectoryInfo:
if store, ok := acct.msgStores[msg.Name]; ok { if store, ok := acct.msgStores[msg.Name]; ok {
store.Update(msg) store.Update(msg)
} else { } else {
acct.msgStores[msg.Name] = lib.NewMessageStore(acct.worker, msg) store = lib.NewMessageStore(acct.worker, msg)
acct.msgStores[msg.Name] = store
store.OnUpdate(func(_ *lib.MessageStore) {
store.OnUpdate(nil)
acct.msglist.SetStore(store)
})
} }
case *types.DirectoryContents: case *types.DirectoryContents:
store := acct.msgStores[acct.dirlist.selected] store := acct.msgStores[acct.dirlist.selected]

View file

@ -109,6 +109,7 @@ func (ml *MessageList) Height() int {
} }
func (ml *MessageList) storeUpdate(store *lib.MessageStore) { func (ml *MessageList) storeUpdate(store *lib.MessageStore) {
ml.logger.Println("message store updated")
if ml.Store() != store { if ml.Store() != store {
return return
} }

View file

@ -17,6 +17,9 @@ func (imapw *IMAPWorker) handleOpenDirectory(msg *types.OpenDirectory) {
}, nil) }, nil)
} else { } else {
imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil) imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
if imapw.idleStop == nil {
imapw.idleStop = make(chan struct{})
}
} }
} }

View file

@ -18,7 +18,7 @@ var errUnsupported = fmt.Errorf("unsupported command")
type imapClient struct { type imapClient struct {
*client.Client *client.Client
*idle.IdleClient idle *idle.IdleClient
} }
type IMAPWorker struct { type IMAPWorker struct {
@ -30,6 +30,8 @@ type IMAPWorker struct {
} }
client *imapClient client *imapClient
idleStop chan struct{}
idleDone chan error
selected imap.MailboxStatus selected imap.MailboxStatus
updates chan client.Update updates chan client.Update
worker *types.Worker worker *types.Worker
@ -39,8 +41,9 @@ type IMAPWorker struct {
func NewIMAPWorker(worker *types.Worker) *IMAPWorker { func NewIMAPWorker(worker *types.Worker) *IMAPWorker {
return &IMAPWorker{ return &IMAPWorker{
updates: make(chan client.Update, 50), idleDone: make(chan error),
worker: worker, updates: make(chan client.Update, 50),
worker: worker,
} }
} }
@ -80,6 +83,13 @@ func (w *IMAPWorker) verifyPeerCert(msg types.WorkerMessage) func(
} }
func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error { func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
if w.idleStop != nil {
close(w.idleStop)
if err := <-w.idleDone; err != nil {
w.worker.PostMessage(&types.Error{Error: err}, nil)
}
}
switch msg := msg.(type) { switch msg := msg.(type) {
case *types.Unsupported: case *types.Unsupported:
// No-op // No-op
@ -167,6 +177,13 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
default: default:
return errUnsupported return errUnsupported
} }
if w.idleStop != nil {
w.idleStop = make(chan struct{})
go func() {
w.idleDone <- w.client.idle.IdleWithFallback(w.idleStop, 0)
}()
}
return nil return nil
} }