Fix IMAP race condition around idle()
`IMAPFolder.idle()` by default keeps idle-ing after each response. We don't need that, because we want to fetch the new mails immediately (over the same connection). To make `idle()` not keep on going, we called `folder.isOpen()` which in most cases makes `idle()` stop by calling `noop()` internally (to keep the connection alive) which leads to the current `idle()`-call being canceled. The problem this commits addresses is that the call to `noop()` only happens if there were no calls in the last second. There is a check for that in `com.sun.mail.imap.IMAPFolder.keepConnectionAlive`. So if a new message appears less then a second after idle started, we will miss it. This new way interrupts `idle()` more often than before, e.g. when there is an expunge-message (i.e. a message was deleted), which we don't care about. But the subsequent `receive()` in IdleTask will simply get no messages and then turn around and start idle-ing again. **Cherry-pick to `5.3.x` & `master`**
This commit is contained in:
committed by
Artem Bilan
parent
3f0c57894b
commit
07a6fb3a9a
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,9 +27,6 @@ import javax.mail.Flags.Flag;
|
||||
import javax.mail.Folder;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.event.MessageCountAdapter;
|
||||
import javax.mail.event.MessageCountEvent;
|
||||
import javax.mail.event.MessageCountListener;
|
||||
import javax.mail.search.AndTerm;
|
||||
import javax.mail.search.FlagTerm;
|
||||
import javax.mail.search.NotTerm;
|
||||
@@ -54,6 +51,7 @@ import com.sun.mail.imap.IMAPFolder;
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @author Alexander Pinske
|
||||
*/
|
||||
public class ImapMailReceiver extends AbstractMailReceiver {
|
||||
|
||||
@@ -61,8 +59,6 @@ public class ImapMailReceiver extends AbstractMailReceiver {
|
||||
|
||||
private static final String PROTOCOL = "imap";
|
||||
|
||||
private final MessageCountListener messageCountListener = new SimpleMessageCountListener();
|
||||
|
||||
private final IdleCanceler idleCanceler = new IdleCanceler();
|
||||
|
||||
private boolean shouldMarkMessagesAsRead = true;
|
||||
@@ -188,16 +184,14 @@ public class ImapMailReceiver extends AbstractMailReceiver {
|
||||
else if (!folder.getPermanentFlags().contains(Flags.Flag.RECENT) && searchForNewMessages().length > 0) {
|
||||
return;
|
||||
}
|
||||
imapFolder.addMessageCountListener(this.messageCountListener);
|
||||
try {
|
||||
this.pingTask = this.scheduler.schedule(this.idleCanceler,
|
||||
new Date(System.currentTimeMillis() + this.cancelIdleInterval));
|
||||
if (imapFolder.isOpen()) {
|
||||
imapFolder.idle();
|
||||
imapFolder.idle(true);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
imapFolder.removeMessageCountListener(this.messageCountListener);
|
||||
if (this.pingTask != null) {
|
||||
this.pingTask.cancel(true);
|
||||
}
|
||||
@@ -276,25 +270,6 @@ public class ImapMailReceiver extends AbstractMailReceiver {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used for handling the event-driven idle response.
|
||||
*/
|
||||
private static class SimpleMessageCountListener extends MessageCountAdapter {
|
||||
|
||||
SimpleMessageCountListener() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messagesAdded(MessageCountEvent event) {
|
||||
Message[] messages = event.getMessages();
|
||||
if (messages.length > 0) {
|
||||
// this will return the flow to the idle call
|
||||
messages[0].getFolder().isOpen();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class DefaultSearchTermStrategy implements SearchTermStrategy {
|
||||
|
||||
DefaultSearchTermStrategy() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -91,6 +91,7 @@ import com.sun.mail.imap.IMAPFolder;
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @author Alexander Pinske
|
||||
*/
|
||||
@SpringJUnitConfig
|
||||
@ContextConfiguration(
|
||||
@@ -607,7 +608,7 @@ public class ImapMailReceiverTests {
|
||||
Thread.sleep(300);
|
||||
shouldFindMessagesCounter.set(1);
|
||||
return null;
|
||||
}).given(folder).idle();
|
||||
}).given(folder).idle(true);
|
||||
|
||||
adapter.start();
|
||||
|
||||
@@ -667,7 +668,7 @@ public class ImapMailReceiverTests {
|
||||
idles.countDown();
|
||||
Thread.sleep(500);
|
||||
return null;
|
||||
}).given(folder).idle();
|
||||
}).given(folder).idle(true);
|
||||
|
||||
adapter.start();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user