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>
This commit is contained in:
parent
e5b339702a
commit
b92efe4cd9
3 changed files with 35 additions and 11 deletions
worker/imap
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue