aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Jarry <robin@jarry.cc>2024-06-28 23:49:20 +0200
committerRobin Jarry <robin@jarry.cc>2024-06-29 00:18:18 +0200
commit446d5303b9c7e7100261fe444bf42319e25e228e (patch)
tree11f65d83bed2fd503d8eeedb30ce023cb0409d82
parent7f833baa90bf6521997c70557a1534dc7528ce0d (diff)
downloadaerc-446d5303b9c7e7100261fe444bf42319e25e228e.tar.gz
jmap: revert fetch threads support
This reverts commits: 9e93d9efdb88 ("jmap: fix go static check failure") 0465509eedad ("jmap: skip Email/get call if no emails to get") 9f97c698e3dd ("jmap: fetch entire threads") Issues have been reported about disappearing sent messages. Reported-by: Tristan Partin <tristan@partin.io> Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Tristan Partin <tristan@partin.io>
-rw-r--r--worker/jmap/cache/gob.go2
-rw-r--r--worker/jmap/cache/state.go13
-rw-r--r--worker/jmap/cache/thread.go35
-rw-r--r--worker/jmap/fetch.go183
-rw-r--r--worker/jmap/state.go26
5 files changed, 32 insertions, 227 deletions
diff --git a/worker/jmap/cache/gob.go b/worker/jmap/cache/gob.go
index 8b153c50..f1b8be33 100644
--- a/worker/jmap/cache/gob.go
+++ b/worker/jmap/cache/gob.go
@@ -6,12 +6,10 @@ import (
"git.sr.ht/~rockorager/go-jmap/mail/email"
"git.sr.ht/~rockorager/go-jmap/mail/mailbox"
- "git.sr.ht/~rockorager/go-jmap/mail/thread"
)
type jmapObject interface {
*email.Email |
- *thread.Thread |
*email.QueryResponse |
*mailbox.Mailbox |
*FolderContents |
diff --git a/worker/jmap/cache/state.go b/worker/jmap/cache/state.go
index 6538ccad..5fec5034 100644
--- a/worker/jmap/cache/state.go
+++ b/worker/jmap/cache/state.go
@@ -12,18 +12,6 @@ func (c *JMAPCache) PutMailboxState(state string) error {
return c.put(mailboxStateKey, []byte(state))
}
-func (c *JMAPCache) GetThreadState() (string, error) {
- buf, err := c.get(threadStateKey)
- if err != nil {
- return "", err
- }
- return string(buf), nil
-}
-
-func (c *JMAPCache) PutThreadState(state string) error {
- return c.put(threadStateKey, []byte(state))
-}
-
func (c *JMAPCache) GetEmailState() (string, error) {
buf, err := c.get(emailStateKey)
if err != nil {
@@ -39,5 +27,4 @@ func (c *JMAPCache) PutEmailState(state string) error {
const (
mailboxStateKey = "state/mailbox"
emailStateKey = "state/email"
- threadStateKey = "state/thread"
)
diff --git a/worker/jmap/cache/thread.go b/worker/jmap/cache/thread.go
deleted file mode 100644
index ca91a4d9..00000000
--- a/worker/jmap/cache/thread.go
+++ /dev/null
@@ -1,35 +0,0 @@
-package cache
-
-import (
- "git.sr.ht/~rockorager/go-jmap"
- "git.sr.ht/~rockorager/go-jmap/mail/thread"
-)
-
-func (c *JMAPCache) GetThread(id jmap.ID) (*thread.Thread, error) {
- buf, err := c.get(threadKey(id))
- if err != nil {
- return nil, err
- }
- e := new(thread.Thread)
- err = unmarshal(buf, e)
- if err != nil {
- return nil, err
- }
- return e, nil
-}
-
-func (c *JMAPCache) PutThread(id jmap.ID, e *thread.Thread) error {
- buf, err := marshal(e)
- if err != nil {
- return err
- }
- return c.put(threadKey(id), buf)
-}
-
-func (c *JMAPCache) DeleteThread(id jmap.ID) error {
- return c.delete(threadKey(id))
-}
-
-func threadKey(id jmap.ID) string {
- return "thread/" + string(id)
-}
diff --git a/worker/jmap/fetch.go b/worker/jmap/fetch.go
index 3c422cbf..17b3fb2f 100644
--- a/worker/jmap/fetch.go
+++ b/worker/jmap/fetch.go
@@ -10,14 +10,12 @@ import (
"git.sr.ht/~rjarry/aerc/worker/types"
"git.sr.ht/~rockorager/go-jmap"
"git.sr.ht/~rockorager/go-jmap/mail/email"
- "git.sr.ht/~rockorager/go-jmap/mail/thread"
"github.com/emersion/go-message/charset"
)
var headersProperties = []string{
"id",
"blobId",
- "threadId",
"mailboxIds",
"keywords",
"size",
@@ -35,90 +33,10 @@ var headersProperties = []string{
"bodyStructure",
}
-func (w *JMAPWorker) fetchEmailIdsFromThreads(threadIds []jmap.ID) ([]jmap.ID, error) {
- currentThreadState, err := w.getThreadState()
- if err != nil {
- return nil, err
- }
-
- // If we can't get the cached mailbox state, at worst, we will just
- // query information we might already know
- cachedThreadState, err := w.cache.GetThreadState()
- if err != nil {
- w.w.Warnf("GetThreadState: %s", err)
- }
-
- consistentThreadState := currentThreadState == cachedThreadState
-
- mailIds := make([]jmap.ID, 0)
- getMailIds := func(threadIds []jmap.ID) error {
- var req jmap.Request
- var realIds []jmap.ID
-
- if len(threadIds) > 0 {
- realIds = threadIds
- } else {
- realIds = []jmap.ID{jmap.ID("00")}
- }
-
- req.Invoke(&thread.Get{
- Account: w.accountId,
- IDs: realIds,
- })
-
- resp, err := w.Do(&req)
- if err != nil {
- return err
- }
-
- for _, inv := range resp.Responses {
- switch r := inv.Args.(type) {
- case *thread.GetResponse:
- for _, t := range r.List {
- mailIds = append(mailIds, t.EmailIDs...)
- }
- case *jmap.MethodError:
- return wrapMethodError(r)
- }
- }
-
- return nil
- }
-
- // If we have a consistent state, check the cache
- if consistentThreadState {
- missingThreadIds := make([]jmap.ID, 0, len(threadIds))
- for _, threadId := range threadIds {
- t, err := w.cache.GetThread(threadId)
- if err != nil {
- w.w.Warnf("GetThread: %s", err)
- missingThreadIds = append(missingThreadIds, threadId)
- continue
- }
- mailIds = append(mailIds, t.EmailIDs...)
- }
-
- if len(missingThreadIds) > 0 {
- if err := getMailIds(missingThreadIds); err != nil {
- return nil, err
- }
- }
- } else {
- if err := getMailIds(threadIds); err != nil {
- return nil, err
- }
- }
-
- if err := w.cache.PutThreadState(currentThreadState); err != nil {
- w.w.Warnf("GetThreadState: %s", err)
- }
-
- return mailIds, nil
-}
-
func (w *JMAPWorker) handleFetchMessageHeaders(msg *types.FetchMessageHeaders) error {
- mailIds := make([]jmap.ID, 0)
- threadIds := make([]jmap.ID, 0, len(msg.Uids))
+ var req jmap.Request
+
+ ids := make([]jmap.ID, 0, len(msg.Uids))
for _, uid := range msg.Uids {
id, ok := w.uidStore.GetKey(uid)
if !ok {
@@ -126,89 +44,52 @@ func (w *JMAPWorker) handleFetchMessageHeaders(msg *types.FetchMessageHeaders) e
}
jid := jmap.ID(id)
m, err := w.cache.GetEmail(jid)
- // TODO: use ID.Valid() when my patch is merged
- if err == nil && len(m.ThreadID) > 0 && len(m.ThreadID) < 256 {
- threadIds = append(threadIds, m.ThreadID)
+ if err == nil {
w.w.PostMessage(&types.MessageInfo{
Message: types.RespondTo(msg),
Info: w.translateMsgInfo(m),
}, nil)
continue
}
- mailIds = append(mailIds, jid)
+ ids = append(ids, jid)
+ }
+
+ if len(ids) == 0 {
+ return nil
}
- postMessages := func(mailIds []jmap.ID, collectThreadIds bool) error {
- missing := make([]jmap.ID, 0, len(mailIds))
- for _, id := range mailIds {
- m, err := w.cache.GetEmail(id)
- // TODO: use ID.Valid() when my patch is merged
- if err == nil && len(m.ThreadID) > 0 && len(m.ThreadID) < 256 {
- threadIds = append(threadIds, m.ThreadID)
+ req.Invoke(&email.Get{
+ Account: w.accountId,
+ IDs: ids,
+ Properties: headersProperties,
+ })
+
+ resp, err := w.Do(&req)
+ if err != nil {
+ return err
+ }
+
+ for _, inv := range resp.Responses {
+ switch r := inv.Args.(type) {
+ case *email.GetResponse:
+ for _, m := range r.List {
w.w.PostMessage(&types.MessageInfo{
Message: types.RespondTo(msg),
Info: w.translateMsgInfo(m),
}, nil)
- continue
- }
- missing = append(missing, id)
- }
-
- if len(missing) == 0 {
- return nil
- }
-
- var req jmap.Request
- req.Invoke(&email.Get{
- Account: w.accountId,
- IDs: missing,
- Properties: headersProperties,
- })
-
- resp, err := w.Do(&req)
- if err != nil {
- return err
- }
-
- for _, inv := range resp.Responses {
- switch r := inv.Args.(type) {
- case *email.GetResponse:
- for _, m := range r.List {
- w.w.PostMessage(&types.MessageInfo{
- Message: types.RespondTo(msg),
- Info: w.translateMsgInfo(m),
- }, nil)
- if err := w.cache.PutEmail(m.ID, m); err != nil {
- w.w.Warnf("PutEmail: %s", err)
- }
-
- if collectThreadIds {
- threadIds = append(threadIds, m.ThreadID)
- }
- }
- if err = w.cache.PutEmailState(r.State); err != nil {
- w.w.Warnf("PutEmailState: %s", err)
+ if err := w.cache.PutEmail(m.ID, m); err != nil {
+ w.w.Warnf("PutEmail: %s", err)
}
- case *jmap.MethodError:
- return wrapMethodError(r)
}
+ if err = w.cache.PutEmailState(r.State); err != nil {
+ w.w.Warnf("PutEmailState: %s", err)
+ }
+ case *jmap.MethodError:
+ return wrapMethodError(r)
}
-
- return nil
- }
-
- if len(mailIds) > 0 {
- if err := postMessages(mailIds, true); err != nil {
- return err
- }
- }
-
- additionalMailIds, err := w.fetchEmailIdsFromThreads(threadIds)
- if err != nil {
- return err
}
- return postMessages(additionalMailIds, false)
+ return nil
}
func (w *JMAPWorker) handleFetchMessageBodyPart(msg *types.FetchMessageBodyPart) error {
diff --git a/worker/jmap/state.go b/worker/jmap/state.go
index 833bd151..3dbab3fb 100644
--- a/worker/jmap/state.go
+++ b/worker/jmap/state.go
@@ -3,7 +3,6 @@ package jmap
import (
"git.sr.ht/~rockorager/go-jmap"
"git.sr.ht/~rockorager/go-jmap/mail/mailbox"
- "git.sr.ht/~rockorager/go-jmap/mail/thread"
)
func (w *JMAPWorker) getMailboxState() (string, error) {
@@ -28,28 +27,3 @@ func (w *JMAPWorker) getMailboxState() (string, error) {
// This should be an impossibility
return "", nil
}
-
-func (w *JMAPWorker) getThreadState() (string, error) {
- var req jmap.Request
-
- // TODO: This is a junk JMAP ID because Go's JSON serialization doesn't
- // send empty slices as arrays, WTF.
- req.Invoke(&thread.Get{Account: w.accountId, IDs: []jmap.ID{jmap.ID("00")}})
- resp, err := w.Do(&req)
- if err != nil {
- return "", err
- }
-
- for _, inv := range resp.Responses {
- switch r := inv.Args.(type) {
- case *thread.GetResponse:
- return r.State, nil
- case *jmap.MethodError:
- return "", wrapMethodError(r)
-
- }
- }
-
- // This should be an impossibility
- return "", nil
-}