-
Notifications
You must be signed in to change notification settings - Fork 12
IDLE DONE doesn't work with Exchange when multiple updates are sent #16
Comments
Can you post debug logs? client.SetDebug(os.Stderr) |
The initial processing finishes with the following:
Then comes the idling part:
|
Hmm. At this point the server is supposed to send:
|
This is an Exchange server, not sure if there are known problems. I also found that the problem occurs if two updates are received from the server in short sequence. For reference, here is the whole test program:
|
Ah, this is interesting. |
I worked around the issue by first "emptying" the
|
One more update: setting
The initialization is
|
The same here. For the test purposes I send an e-mail to myself and receive two mailbox updates one after another in a quick succession. If after the first update I close the
and then wait for
the program hangs indefinitely. |
It looks like Line 60 in f05f546
and then here: Lines 33 to 38 in f05f546
|
has this been fixed? I am also seeing a lock up when doing |
I have the same problem, but with dovecot imap server instead of Exchange. As @andreasbenzing has pointed out, it looks like when you close the stop channel My solution to the problem is to nil the updates channel before closing the idle:
And recreate the channel just before entering into another idle. I guess another option will be to have a permanent goroutine listening to updates and consuming the updates channel. |
+1 with double I Guess this happens when a response have these two line:
The relevant codes are here: switch name {
case "EXISTS":
// ...
if c.Updates != nil {
c.Updates <- &MailboxUpdate{c.Mailbox()}
}
case "RECENT":
// ...
if c.Updates != nil {
c.Updates <- &MailboxUpdate{c.Mailbox()}
}
} A quick solution came into my mind is that we hold updates in the response struct, which are shared between handling: // DataResp is an IMAP response containing data.
type DataResp struct {
// The response tag. Can be either "" for untagged responses, "+" for continuation
// requests or a previous command's tag.
Tag string
// The parsed response fields.
Fields []interface{}
Updates map[UpdateType]interface{}
} After we collect all updates, fires them at the last. |
BTW: I introduced a throttle func to limit the executing, which also benefits when server send notification densely. func throttle(fn OnUpdate, delay time.Duration) OnUpdate {
lock := sync.Mutex{}
prevs := make(map[reflect.Type]*time.Timer)
return func(mailbox string, update interface{}) {
lock.Lock()
defer lock.Unlock()
tp := reflect.TypeOf(update)
if prev, ok := prevs[tp]; ok {
prev.Stop()
}
prevs[tp] = time.AfterFunc(delay, func() {
fn(mailbox, update)
})
}
} |
I tried to get the updated messages as described by @taisph in #11 (comment)
However, the client hangs on the last
<-done
How can I interrupt idling to fetch mails from the update?
The text was updated successfully, but these errors were encountered: