Thread: [Logicmail-devel] Upcoming mail store services refactoring
Brought to you by:
octorian
From: Derek K. <dko...@lo...> - 2011-08-10 02:16:40
|
If you don't want the back-story, feel free to skip to the mark. :-) Oh, and sorry for the endless rambling here. Just want to keep people somewhat informed, given that I know the code is being reused downstream. Ever since the 2.0 code started coming together about a year ago, I've been trying to figure out where to hide all the ugliness between the asynchronous request-based mail store layer of the application and the data model layer. The ugliness I'm referring to, is the code that breaks a high-level data model request (e.g. "load/refresh this message") into a collection of cache and mail store operations. Initially, this was scattered throughout the data model classes (e.g. MessageNode, MailboxNode, etc.) and was getting out of control. After much head-banging, I solved the problem by creating a "services layer" in the data model package, to act as a facade between the rest of the data model and the mail store. Within it, I was able to localize all of this nasty code. (This layer is composed primarily of "MailStoreServices", "FolderRequestHandler", and their sub-classes.) In the 2.0 code, this still appears overcomplicated because the mail store requests are not really object-oriented. (This lead to a mess of trying to match requests with conceptually-request-independent mail store events, since the request success/failure callbacks didn't provide much information.) The first major change I did in the 2.1 (trunk) code, was to completely refactor the mail store requests to be fully object-oriented. This is somewhat obvious due to the massive increase in the number of classes in the "mail" package. Due to this, I was able to change the mail store services layer to follow a pattern where it only cares about the now-useful request callbacks when managing complex operations. (mail store events are directly passed through, and just looked at for cache updates) -->MARK The actual mail complex mail store services requests (e.g. "load a message", "refresh a folder", "refresh a collection of folders", etc.) are still very ugly-looking in their implementation. While I've cleaned it up a lot (see above), there are still many cases where it is getting messy again. This is especially true with multiple-folder refresh (i.e. "check all my mail folders in the background, every 10 minutes, and notify on new messages"). It also seems like bugs are starting to creep back into these cases. (Seen a sporadic mailbox-goes-blank when background-refresh is enabled, and flag changes during message load also causes issues.) I really just need to clean up these process flows so bugs can't creep in from unexpected events. Each one of these operations can be represented kind of like a state machine, and I should eventually be able to document them as such also. So what I'm going to be doing, is gradually refactoring these complex services operations into something resembling the Java state pattern. I started tonight, with the basic message loading process (which is anything but basic). Once I achieve a sufficient level of stability in my implementation, I'll start committing code. Most likely, this will involve some variation of the following classes inside the "model" package: ServicesRequestContext - context/control class ServicesRequestState - interface all state objects implement ServicesMailStoreRequestState - customized abstract state object designed to wrap mail store requests I'll then create subclasses of ServicesRequestContext for each complex operation. Of course this may change as I work through the implementation, especially if I start working towards using a hierarchical state machine for things like multiple-folder-refresh (where I want to disable/enable IMAP IDLE on either end). -- ---------------------------- Derek Konigsberg dko...@lo... ---------------------------- |
From: Derek K. <dko...@lo...> - 2011-08-12 02:09:07
|
Note: This is more developer-in-the-weeds stream-of-consciousness I just wanted to let you know that after a first pass at everything I rambled at in the last message, and a lot of thinking, I've come up with a much simpler and cleaner solution that I'm currently working through the implementation of. Basically, it occurred to me that the original reason for all the nastiness in the services layer was because of the v2.0 mail store request implementation. It really was nothing but a thin wrapper around mail protocol commands. Everything I proposed doing in my last ramble, and a few considered variations thereof, was just going to add to the complexity of it all by building more infrastructure in the wrong layer of the application. So here's what I'm actually working through now: I'm creating the more complex requests *inside* the mail store layer. The services layer will still be responsible for cache loading (upfront) and updates (by intercepting mail store events). However, the rest of the protocol-dependent processes are going to solely be the responsibility of the mail store layer. (So far, this actually improves performance as well, though it still needs a lot of testing before I can check it in.) I'll then be able to dramatically simply the code in FolderRequestHandler, and probably even remove its IMAP and POP specific subclasses. I may eventually simplify NetworkMailStoreServices as well. Hopefully, the only complicated thing I'll have to come up with a cleaner solution for, is chaining folder refresh operations together (or queuing operations after folder refreshes). However, given that these big operations are now singular requests according to the mail store, I may be able to remove the quirky "enable/disable IMAP idle" administrative operations around them. -Derek On 08/09/2011 10:16 PM, Derek Konigsberg wrote: > If you don't want the back-story, feel free to skip to the mark. :-) > Oh, and sorry for the endless rambling here. Just want to keep people > somewhat informed, given that I know the code is being reused downstream. > > Ever since the 2.0 code started coming together about a year ago, I've > been trying to figure out where to hide all the ugliness between the > asynchronous request-based mail store layer of the application and the > data model layer. > > The ugliness I'm referring to, is the code that breaks a high-level data > model request (e.g. "load/refresh this message") into a collection of > cache and mail store operations. Initially, this was scattered > throughout the data model classes (e.g. MessageNode, MailboxNode, etc.) > and was getting out of control. -- ---------------------------- Derek Konigsberg dko...@lo... ---------------------------- |
From: Derek K. <dko...@lo...> - 2011-08-13 04:00:02
|
Okay, this is my final (fingers crossed) message on this topic. I've just checked in my work so far, and here's what I've done: - Created two new "mail store" requests, containing 90% of the convoluted logic that used to be in the FolderRefreshHandler classes of the "services" layer: - ImapFolderRefreshRequest - PopFolderRefreshRequest - Cleaned up the "services" layer based on the knowledge that due to the above, complex folder refresh/sync operations are now single requests within the mail store. - Drastically simplified the multi-folder refresh logic to simply queue up a whole bunch of these refresh requests within the mail store. Hopefully I didn't break anything, but I'll continue to test-and-fix as I start running the code on my personal device. Eventually, if I get around to implementing IMAP's QRESYNC extension, it'll now be a lot easier. It'll just be an alternate refresh request implementation. (If I do that, IMAP folder refreshes will become significantly more efficient for servers that support it.) Due to these changes, users will hopefully notice the following: - Folder refreshes should now show a single updating status message (instead of 2-3 show/hides of the status bar). - Folder refreshes should be a little bit faster, due to a lot less round-tripping between layers of the app. P.S. Any further work on this will be cleanup, and not worth writing E-Mails about. -Derek On 08/11/2011 10:08 PM, Derek Konigsberg wrote: > I'm creating the more complex requests *inside* the mail store layer. > The services layer will still be responsible for cache loading (upfront) > and updates (by intercepting mail store events). However, the rest of > the protocol-dependent processes are going to solely be the > responsibility of the mail store layer. (So far, this actually improves > performance as well, though it still needs a lot of testing before I can > check it in.) -- ---------------------------- Derek Konigsberg dko...@lo... ---------------------------- |