From f9113810cc6cace71ab4dc506f1b106e4ae9f8dd Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Sat, 11 May 2024 14:15:04 -0500 Subject: jmap: invalidate cache if mailbox state is not consistent We weren't checking if the cached state was the same as the remote state before reading it. This led to aerc not knowing about new mailboxes on the remote. Signed-off-by: Tristan Partin Acked-by: Robin Jarry --- worker/jmap/directories.go | 39 ++++++++++++++++++++++++++++----------- worker/jmap/state.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 worker/jmap/state.go (limited to 'worker') diff --git a/worker/jmap/directories.go b/worker/jmap/directories.go index bc47e691..eac63398 100644 --- a/worker/jmap/directories.go +++ b/worker/jmap/directories.go @@ -21,21 +21,38 @@ func (w *JMAPWorker) handleListDirectories(msg *types.ListDirectories) error { mboxes = make(map[jmap.ID]*mailbox.Mailbox) - mboxIds, err := w.cache.GetMailboxList() - if err == nil { - for _, id := range mboxIds { - mbox, err := w.cache.GetMailbox(id) - if err != nil { - w.w.Warnf("GetMailbox: %s", err) - missing = append(missing, id) - continue + currentMailboxState, err := w.getMailboxState() + if err != nil { + return err + } + + // If we can't get the cached mailbox state, at worst, we will just + // query information we might already know + cachedMailboxState, err := w.cache.GetMailboxState() + if err != nil { + w.w.Warnf("PutMailboxState: %s", err) + } + + consistentMailboxState := currentMailboxState == cachedMailboxState + + // If we have a consistent state, check the cache + if consistentMailboxState { + mboxIds, err := w.cache.GetMailboxList() + if err == nil { + for _, id := range mboxIds { + mbox, err := w.cache.GetMailbox(id) + if err != nil { + w.w.Warnf("GetMailbox: %s", err) + missing = append(missing, id) + continue + } + mboxes[id] = mbox + ids = append(ids, id) } - mboxes[id] = mbox - ids = append(ids, id) } } - if err != nil || len(missing) > 0 { + if !consistentMailboxState || len(missing) > 0 { var req jmap.Request req.Invoke(&mailbox.Get{Account: w.accountId}) diff --git a/worker/jmap/state.go b/worker/jmap/state.go new file mode 100644 index 00000000..3dbab3fb --- /dev/null +++ b/worker/jmap/state.go @@ -0,0 +1,29 @@ +package jmap + +import ( + "git.sr.ht/~rockorager/go-jmap" + "git.sr.ht/~rockorager/go-jmap/mail/mailbox" +) + +func (w *JMAPWorker) getMailboxState() (string, error) { + var req jmap.Request + + req.Invoke(&mailbox.Get{Account: w.accountId, IDs: make([]jmap.ID, 0)}) + resp, err := w.Do(&req) + if err != nil { + return "", err + } + + for _, inv := range resp.Responses { + switch r := inv.Args.(type) { + case *mailbox.GetResponse: + return r.State, nil + case *jmap.MethodError: + return "", wrapMethodError(r) + + } + } + + // This should be an impossibility + return "", nil +} -- cgit