refactor(mail): IMAP and the webmail read folders and messages through one MailStore
The folder list and the message list were two queries over the same tables. IMAP took a folder's message count from a cached column and the webmail counted rows, so the two could disagree. Both now ask MailStore, which counts the messages.
This commit is contained in:
1 parent
a8941a6191
commit
67bbe7a50a
4 files changed
+287
-155
No files matched your search
@@ -8,37 +8,26 @@ import (
|
||||
"lambdamail/protocols/internal/application/port"
|
||||
)
|
||||
|
||||
// MessageQueryRepository implements port.MessageQueryRepository against Postgres.
|
||||
// MessageQueryRepository lists a folder's messages for IMAP FETCH, through the
|
||||
// same MailStore listing the webmail uses.
|
||||
type MessageQueryRepository struct {
|
||||
pool *pgxpool.Pool
|
||||
store *MailStore
|
||||
}
|
||||
|
||||
func NewMessageQueryRepository(pool *pgxpool.Pool) *MessageQueryRepository {
|
||||
return &MessageQueryRepository{pool: pool}
|
||||
return &MessageQueryRepository{store: NewMailStore(pool)}
|
||||
}
|
||||
|
||||
func (r *MessageQueryRepository) ListMessages(ctx context.Context, folderID string) ([]port.MessageRecord, error) {
|
||||
rows, err := r.pool.Query(ctx, `
|
||||
SELECT m.uid, m.blob_id, m.size_bytes, m.received_at, m.modseq,
|
||||
COALESCE(array_agg(f.flag) FILTER (WHERE f.flag IS NOT NULL), '{}')
|
||||
FROM email_messages m
|
||||
LEFT JOIN message_flags f ON f.message_id = m.id AND f.received_at = m.received_at
|
||||
WHERE m.folder_id = $1 AND m.expunged_at IS NULL
|
||||
GROUP BY m.uid, m.blob_id, m.size_bytes, m.received_at, m.modseq
|
||||
ORDER BY m.uid ASC
|
||||
`, folderID)
|
||||
messages, err := r.store.Messages(ctx, folderID, MessageQuery{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var out []port.MessageRecord
|
||||
for rows.Next() {
|
||||
var rec port.MessageRecord
|
||||
if err := rows.Scan(&rec.UID, &rec.BlobID, &rec.SizeBytes, &rec.ReceivedAt, &rec.ModSeq, &rec.Flags); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, rec)
|
||||
for _, m := range messages {
|
||||
out = append(out, port.MessageRecord{
|
||||
UID: m.UID, BlobID: m.BlobID, SizeBytes: m.Size, ReceivedAt: m.ReceivedAt, Flags: m.Flags, ModSeq: m.ModSeq,
|
||||
})
|
||||
}
|
||||
return out, rows.Err()
|
||||
return out, nil
|
||||
}
|
||||
Reference in new issue
Block a user