~rjarry/aerc-devel

aerc: imap: drain updates channel when deleting messages v1 APPLIED

Koni Marti: 1
 imap: drain updates channel when deleting messages

 1 files changed, 40 insertions(+), 0 deletions(-)
#1157023 alpine-edge.yml success
#1157024 openbsd.yml success
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~rjarry/aerc-devel/patches/49788/mbox | git am -3
Learn more about email & git

[PATCH aerc] imap: drain updates channel when deleting messages Export this patch

Drain the buffered updates channel when deleting messages to prevent a
backend freeze. Unilateral update messages from the IMAP server can fill
up the buffered channel if not handled during a large operation (more
than ~50 messages).

Link: https://lists.sr.ht/~rjarry/aerc-discuss/%3CCZCPBTWI3PIW.T8MWNCBG7FGL%40disroot.org%3E
Changelog-fixed: Prevent a freeze for large-scale deletions with IMAP.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
---
 worker/imap/flags.go | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/worker/imap/flags.go b/worker/imap/flags.go
index 06680818..60137bd3 100644
--- a/worker/imap/flags.go
+++ b/worker/imap/flags.go
@@ -2,13 +2,53 @@ package imap

import (
	"github.com/emersion/go-imap"
	"github.com/emersion/go-imap/client"

	"git.sr.ht/~rjarry/aerc/lib/log"
	"git.sr.ht/~rjarry/aerc/models"
	"git.sr.ht/~rjarry/aerc/worker/types"
)

// drainUpdates will drain the updates channel. For some operations, the imap
// server will send unilateral messages. If they arrive while another operation
// is in progress, the buffered updates channel can fill up and cause a freeze
// of the entire backend. Avoid this by draining the updates channel and only
// process the Message and Expunge updates.
//
// To stop the draining, close the returned struct.
func (imapw *IMAPWorker) drainUpdates() *drainCloser {
	done := make(chan struct{})
	go func() {
		defer log.PanicHandler()
		for {
			select {
			case update := <-imapw.updates:
				switch update.(type) {
				case *client.MessageUpdate,
					*client.ExpungeUpdate:
					imapw.handleImapUpdate(update)
				}
			case <-done:
				return
			}
		}
	}()
	return &drainCloser{done}
}

type drainCloser struct {
	done chan struct{}
}

func (d *drainCloser) Close() error {
	close(d.done)
	return nil
}

func (imapw *IMAPWorker) handleDeleteMessages(msg *types.DeleteMessages) {
	drain := imapw.drainUpdates()
	defer drain.Close()

	item := imap.FormatFlagsOp(imap.AddFlags, true)
	flags := []interface{}{imap.DeletedFlag}
	uids := toSeqSet(msg.Uids)
-- 
2.44.0
aerc/patches: SUCCESS in 2m11s

[imap: drain updates channel when deleting messages][0] from [Koni Marti][1]

[0]: https://lists.sr.ht/~rjarry/aerc-devel/patches/49788
[1]: mailto:koni.marti@gmail.com

✓ #1157024 SUCCESS aerc/patches/openbsd.yml     https://builds.sr.ht/~rjarry/job/1157024
✓ #1157023 SUCCESS aerc/patches/alpine-edge.yml https://builds.sr.ht/~rjarry/job/1157023
Koni Marti <koni.marti@gmail.com> wrote: