Mailbox state machine (Mailnews Exchange support)

Previously I have described interfaces that allowed me to display Exchange Web Server objects in Thunderbird’s folder tree and account manager. My goal lately has been to display lists of messages in the thread pane. To do that, I have to acquire, store and interface message metadata (the message summary database) to the Mozilla mailnews interfaces.

Unfortunately an issue has loomed too large to ignore: the need to sequence a number of SOAP requests when I need to send multiple requests to meet a single goal. Previously I had simply kludged around this, but I needed to make some decisions to be able to move forward in an orderly manner.

I’m also having enormous problems deciding what to name things. So before I can even talk about what I decided to do, I need to give a little lesson on the naming that surrounds my architecture.

Overall Architecture

Since my last diagram, I have clarified things a little, so the structure now looks like this:

The architectural layers are:

Mailnews: the existing Mozilla Mailnews code and objects.

Colonial: the Colonial layer provides the glue between objects represented in Mozilla mailnews format, and Exchange server format. The “colonial” analogy is an extension of the “native” layer analogy presented earlier. That is, if we picture Mozilla mailnews as the mother country, trying to make sense of some aboriginal “native” tribe, then there exists a colonial administration that pretends to have the same laws as the mother country, but has to translate all of those laws into some sort of actions involving native people. So the objects that pretend to be following the laws of the mother country (Mozilla mailnews), but in fact really exist in some other culture, are Colonial objects.

In my architecture, the Colonial objects are subclasses of base Mailnews objects like nsMsgDatabase, nsMsgDBFolder, nsMsgIncomingServer, etc.

Native: This layer’s objects exist as XPCOM objects on the Mozilla platform, but are represented in the native “Exchange” format rather than in Mailnews format. So for example they are identified primarily by string object ids (and not integer keys like Mailnews objects), and they are located in the Exchange tree. For example, folders containing contacts, the inbox, and tasks are all subfolders of a root mailbox folder, as in Exchange Server.

EWS: This layer provides translation of methods to perform operations on native-layer objects (like get subfolders, or sync message metadata) with objects that can be directly translated into SOAP web calls. (I actually use an intermediate representation, called a “property list”, that is very similar to an nsIPropertyBag, but supports ordered, multiple-valued lists such as are present in the SOAP protocols. But these property list objects can be translated directly into the SOAP protocol using the schema provided by Exchange Web Services).

SOAP: As discussed earlier, this is an updated version of Mozilla’s abandoned webservices package.

Exchange: The Exchange Messaging Server itself, implementing a SOAP interface.

State Machine to implement Mailnews Object methods

Let me now describe the problem, and what I decided to do. This is the msqEwsMachine class in the diagram.

The interface to Mozilla mailnews frequently consists of methods that are executed on mailnews interfaces, for example nsIMsgFolder.getNewMessages(). Such methods will get translated into a sequence of requests to a web server, which leave the SOAP layer as a sequence of nsXMLHttpRequests.

Which object is responsible for taking the method call, managing the series of requests to the web server, and generating appropriate events and callbacks when the method has been completed? That has been the issue of the last two weeks.

Originally, I had it done by the colonial-layer representation of nsIMsgIncomingServer, msqEwsIncomingServer. But I did not like how that forced the incoming server object to know way too much about the details of the SOAP calls, when at that layer all it really needed to know was the data results. I also tested using the service layer objects, either the colonial layer object that implements nsIMsgMessageService, or its Native-layer counterpart. But I found that everything that I did needed access to the root of the Native layer data representation, which is the native mailbox object.

So that is where the management ended up: methods on an object, msqEwsMachine, which is fully owned by the the native-layer mailbox object (The mailbox is the native-layer analog of nsIMsgIncomingServer).

A simple request to the mailbox layer would be “discover subfolders”, which requests that the Exchange server provide a list of all defined folders, their parent/child relationship, and some basic folder properties such as the display name. That requires two SOAP requests: 1) a first to translate the so-called “DistinguishedFolderId” such as “inbox” into the guid equivalent for the limited number of distinguished folders, and 2) a second call where the root folder is asked for all of its children recursively. At the end of the whole process, an “onStop” event is generated, which will ultimately be translated into the appropriate mailnews notifications.

Next step: message metadata and nsIMsgDBHdr

Yes this has been a rather boring post, but I didn’t want anyone to think nothing was happening! As the next step, I am now ready to start generating a list of messages per folder, and their corresponding nsIMsgDBHdr objects. Then I can show messages in the thread pane.

Share

3 comments to Mailbox state machine (Mailnews Exchange support)

  • Kent, I think you are on the right track with your use of a state machine.

    The Zindus addon implements a Mealy Machine:

    http://en.wikipedia.org/wiki/Finite_state_machine#Transducers

    and experience has shown this to be a very useful design pattern in:
    - maintaining consistency
    - knowing when consistency is lost
    - co-ordinating changes in state across local and remote authorities

    re: “colonial” terminology: I can see why you chose it, but it implies a master/slave relation and when push comes to shove (ie when consistency is lost and need to be re-established) is “thunderbird” really likely to be the source of truth that is propagated to exchange? I would have thought the reverse or at least that tb and exchange are peers.

    • “The Zindus addon implements a Mealy Machine” – thanks for the reference. I’ll check that out to see if a Mealy Machine provides the correct framework to maintain consistency in my design.

      re “colonial” – A name is just a name, and there is no reason to carry the analogy into the actual design, ie “is “thunderbird” really likely to be the source of truth that is propagated to exchange?” As to “I would have thought the reverse”, you are right that at some level “tb and exchange are peers.”. After I started using “native” to name the Mozilla platform Exchange objects, I realized that it was just as valid to view the Mozilla mailnews objects as “native” and Exchange as somehow “foreign”. But they are peers, and who is the native and who is the foreigner depends entirely on your perspective.

      By the way, I did a posting on m.d.a.t proposing to call the Mozilla Mailnews layer by a more distinctive name, “Skink”. This conversation is a typical example of where I would love to have a better word for those objects than “Mozilla Mailnews” – bugt I got zero traction on that.

  • [...] that I have a state machine to handle situations that need multiple SOAP calls, it was not a big leap forward to hookup the [...]

Leave a Reply

  

  

  

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

To comment, click below to log in.