Skip to content
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

Closed
wants to merge 3 commits into from
Closed

Rewrite IMAP IDLE #2671

wants to merge 3 commits into from

Conversation

rhari991
Copy link

@rhari991 rhari991 commented Aug 9, 2017

This PR builds upon the changes made to ImapFolderPusher in PR #2607 by

  • Removing all the code that processes the various IDLE responses
  • Making it not extend ImapFolder anymore
  • Not sending DONE and IDLE commands whenever a useful response is received through IDLE

@rhari991 rhari991 requested review from jberkel and Valodim and removed request for jberkel August 9, 2017 19:02
@philipwhiuk
Copy link
Contributor

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;
Copy link
Contributor

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?

Copy link
Author

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.

@rhari991 rhari991 force-pushed the rewrite-imap-idle branch 4 times, most recently from 0caf0c0 to ecc6a66 Compare August 18, 2017 02:40

folderPusher.start();

verify(pushReceiver).syncFolder(FOLDER_NAME);
Copy link
Author

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 ?

@rhari991 rhari991 force-pushed the rewrite-imap-idle branch 6 times, most recently from be32ac2 to 5660ab0 Compare August 20, 2017 17:42
Copy link
Contributor

@Valodim Valodim left a 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 {
Copy link
Contributor

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?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Author

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();
Copy link
Contributor

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

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

Copy link
Contributor

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

Copy link
Author

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();
Copy link
Contributor

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

Copy link
Author

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);
Copy link
Contributor

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.

Copy link
Author

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++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(code style)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

@rhari991 rhari991 force-pushed the condstore-support branch 2 times, most recently from 33dc02c to 75a0452 Compare September 12, 2017 03:41
@lucafavatella
Copy link

I have the impression this PR was rendered meaningless by an erroneous force-push potentially related to PR 2701, because:

  • I see title with "IDLE", but no IDLE-related changes;
  • I see review comments on file ImapFolderPusher.java now absent.

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.

@philipwhiuk
Copy link
Contributor

@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.

@cketti cketti closed this Jul 3, 2021
@cketti cketti deleted the rewrite-imap-idle branch January 28, 2023 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants