-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rewrite IMAP IDLE #2671
Rewrite IMAP IDLE #2671
Conversation
I'm happy to review this, but there's not much point until the tests pass.. |
private static final int IDLE_READ_TIMEOUT_INCREMENT = 5 * 60 * 1000; | ||
private static final int IDLE_FAILURE_COUNT_LIMIT = 10; | ||
private static final int MAX_DELAY_TIME = 5 * 60 * 1000; // 5 minutes | ||
private static final int NORMAL_DELAY_TIME = 5000; | ||
|
||
|
||
private final ImapFolder folder; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a thought: there aren't a lot of references to this folder object, and those I saw either worked on the ImapConnection or ImapStore, and especially in the case of ImapConnection we partly manage that object ourselves here which leads to weird coupling between the classes. Perhaps we can easily get rid of this dependency here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how to do that, since the folder / the folder name needs to saved in between calls to the constructor and the start()
/ stop()
methods. Since each instance of ImapFolderPusher
manages a single folder, I think it is appropriate to have it as an instance variable.
68a688b
to
cf1bc5d
Compare
0caf0c0
to
ecc6a66
Compare
|
||
folderPusher.start(); | ||
|
||
verify(pushReceiver).syncFolder(FOLDER_NAME); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Valodim When I debug this test, this invocation does occur, but this verification still fails. Is there something I am missing here ?
be32ac2
to
5660ab0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good start, I like that ImapFolderPusher
lost quite a bit of weight. I don't quite like how the object uses both ImapFolder and its underlying ImapConnection at the moment. Ideally it should access the folder, or the connection object, not both. It's possible that that's too complicated, please look into it.
Timber.v("Got async response: %s", response); | ||
} | ||
|
||
public void handleAsyncUntaggedResponse(ImapResponse response) throws IOException, MessagingException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while you're at it, please change this into an anonymous inner class rather than having PushRunnable implement the interface. that way the executeSimpleCommand(Commands.IDLE, this)
becomes executesimpleCommand(Commands.IDLE, untaggedResponseHandler)
, which makes it easier to trace where the handling happens in the IDE.
e.g.
private UntaggedHandler untaggedResponseHandler = new UntaggedHandler() {
...
}
(also, is this really "async"? it's a callback that is called in the thread that runs executeSimpleCommand
, isn't it?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is async in the sense that executeSimpleCommand(Commands.IDLE, untaggedhandler)
is a long blocking call, and while it is blocking, handleAsyncUntaggedResponse
is called to process a response.
synchronized (storedUntaggedResponses) { | ||
storedUntaggedResponses.add(response); | ||
if (!folder.getConnection().areMoreResponsesAvailable()) { | ||
processStoredUntaggedResponses(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this entire block is conditional (response.size()
and isUntaggedResponseSupported
above), but it should probably always trigger if no more responses are available
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is changed, but not fixed I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Valodim Sorry, I thought you were talking about the indentation. I have moved the processing command to the end of the method.
@@ -327,10 +298,10 @@ private void returnFromIdle() { | |||
} | |||
|
|||
private boolean openConnectionIfNecessary() throws MessagingException { | |||
ImapConnection oldConnection = connection; | |||
internalOpen(OPEN_MODE_RO, INVALID_UID_VALIDITY, INVALID_HIGHEST_MOD_SEQ); | |||
ImapConnection oldConnection = folder.getConnection(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doing this from a getter is a hack, see comment above on the ImapConnection responsibility
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the getter.
if (K9MailLib.isDebug()) { | ||
Timber.i("About to IDLE for %s", getLogId()); | ||
} | ||
|
||
prepareForIdle(); | ||
|
||
ImapConnection conn = connection; | ||
ImapConnection conn = folder.getConnection(); | ||
setReadTimeoutForIdle(conn); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the responsibility of ImapConnection is weirdly distributed here: the timeout is set directly on the connection from ImapFolder, but the executeSimpleCommand
then is run by the folder itself. is the connection supposed to be managed by the ImapFolder, or not?
If it is, we should try to do as little on this object as possible, ideally get rid of the getter. But manipulating the ImapConnection object that is otherwise managed by ImapFolder feels wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some places where it is appropriate to manage the connection directly, like setReadTimeout
and not through the folder. I decided to create a new class IdleConnectionManager
that wraps an ImapConnection
object and exposes only the necessary method to ImapFolderPusher
. I also moved all the code from the IdleStopper
class into it.
untaggedResponses.size(), getLogId()); | ||
} | ||
|
||
for (int i = 0; i < untaggedResponses.size();i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(code style)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed
c296d8a
to
033f702
Compare
8e03dc0
to
7831ffe
Compare
33dc02c
to
75a0452
Compare
I have the impression this PR was rendered meaningless by an erroneous force-push potentially related to PR 2701, because:
I see this PR at commit 1dcbaa7. I suggest ensuring an issue is open by distilling PR title and PR description, and then closing this PR. |
@lucafavatella This is part of a GSoC project finalisation step. There's already issues surrounding it. It'll be closed when it's merged / @rhari991 finishes the hard work they have done surrounding IDLE and CONDSTORE. |
This PR builds upon the changes made to
ImapFolderPusher
in PR #2607 byImapFolder
anymore