aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKoni Marti <koni.marti@gmail.com>2022-04-30 01:08:57 +0200
committerRobin Jarry <robin@jarry.cc>2022-05-04 14:07:15 +0200
commitb92efe4cd944c97bf8310ca47d4edbef968cfaae (patch)
treeae9a99efa86fea6087673612f969226d49a9e9da
parente5b339702a56fa02dedec770a79b64313fb30108 (diff)
downloadaerc-b92efe4cd944c97bf8310ca47d4edbef968cfaae.tar.gz
imap: add debouncer to the idler
Add a debouncer to the idle mode. Avoid unnecessary idling when another job arrives within a certain time frame. For example, the ui sends three messages to the worker at the same time when we open a message (FlagMessage, FetchMessageBodyPart, and the FetchMessageHeaders). The debouncer prevents the unnecessary entering and leaving of the idle mode between those messages. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
-rw-r--r--worker/imap/configure.go11
-rw-r--r--worker/imap/idler.go34
-rw-r--r--worker/imap/worker.go1
3 files changed, 35 insertions, 11 deletions
diff --git a/worker/imap/configure.go b/worker/imap/configure.go
index c25600df..ddaaf93f 100644
--- a/worker/imap/configure.go
+++ b/worker/imap/configure.go
@@ -45,7 +45,10 @@ func (w *IMAPWorker) handleConfigure(msg *types.Configure) error {
w.config.user = u.User
w.config.folders = msg.Config.Folders
+
w.config.idle_timeout = 10 * time.Second
+ w.config.idle_debounce = 10 * time.Millisecond
+
w.config.connection_timeout = 30 * time.Second
w.config.keepalive_period = 0 * time.Second
w.config.keepalive_probes = 3
@@ -63,6 +66,14 @@ func (w *IMAPWorker) handleConfigure(msg *types.Configure) error {
value, err)
}
w.config.idle_timeout = val
+ case "idle-debounce":
+ val, err := time.ParseDuration(value)
+ if err != nil || val < 0 {
+ return fmt.Errorf(
+ "invalid idle-debounce value %v: %v",
+ value, err)
+ }
+ w.config.idle_debounce = val
case "reconnect-maxwait":
val, err := time.ParseDuration(value)
if err != nil || val < 0 {
diff --git a/worker/imap/idler.go b/worker/imap/idler.go
index e9aecfd9..bac690f1 100644
--- a/worker/imap/idler.go
+++ b/worker/imap/idler.go
@@ -25,6 +25,7 @@ type idler struct {
config imapConfig
client *imapClient
worker *types.Worker
+ last time.Time
stop chan struct{}
done chan error
waiting bool
@@ -63,20 +64,31 @@ func (i *idler) isReady() bool {
func (i *idler) Start() {
if i.isReady() {
i.stop = make(chan struct{})
+
go func() {
defer logging.PanicHandler()
- i.idleing = true
- i.log("=>(idle)")
- now := time.Now()
- err := i.client.Idle(i.stop,
- &client.IdleOptions{
- LogoutTimeout: 0,
- PollInterval: 0,
- })
- i.idleing = false
- i.done <- err
- i.log("elapsed ideling time:", time.Since(now))
+ select {
+ case <-i.stop:
+ // debounce idle
+ i.log("=>(idle) [debounce]")
+ i.done <- nil
+ case <-time.After(i.config.idle_debounce):
+ // enter idle mode
+ i.idleing = true
+ i.log("=>(idle)")
+ now := time.Now()
+ err := i.client.Idle(i.stop,
+ &client.IdleOptions{
+ LogoutTimeout: 0,
+ PollInterval: 0,
+ })
+ i.idleing = false
+ i.done <- err
+ i.log("elapsed idle time:",
+ time.Since(now))
+ }
}()
+
} else if i.isWaiting() {
i.log("not started: wait for idle to exit")
} else {
diff --git a/worker/imap/worker.go b/worker/imap/worker.go
index 6e475305..1ff6341f 100644
--- a/worker/imap/worker.go
+++ b/worker/imap/worker.go
@@ -43,6 +43,7 @@ type imapConfig struct {
folders []string
oauthBearer lib.OAuthBearer
idle_timeout time.Duration
+ idle_debounce time.Duration
reconnect_maxwait time.Duration
// tcp connection parameters
connection_timeout time.Duration