Saturday 26 November 2011

Message Sequence Charts


I love me some message sequence charts. I have been using them off and on since I first learned about them in the early '80's. Whenever I have a timing problem, a race condition to explore, a set of interlocked state machines, or some protocols that have to work with each other, I fire up my MSC machine. In my case, the MSC machine is usually a pad of paper, or, when I need to share my thoughts with others, a white board.

Less often, I will use a graphics package, even a CASE package, to put my thoughts into the computer for more permanent documentation. Somehow, the formality of the medium changes the process. I am no longer capturing my thoughts; I am doing "documentation." Putting pen to paper is more exploratory, in my experience, than is using a text editor, word processor, or CASE system.

Either way you choose to do it is fine. The important point is that message sequence charts will bolster your communications, and help you identify problems in the system you are working with. As you explain to your colleagues where you think the problem lies, the MSC will highlight the vulnerabilities; as they explain to you where they think the problem lies, they will refer to the MSC over and over again. It its a sure fire conversation lubricant.

How Do The Sequence Charts Work?

First, you identify the players and then you identify how they communicate and when. We are often faced with a bunch of stock elements, with a familiar cast of characters. We want to see how we might treat those characters.

Let's look at a "typical", blog-style example: a web application. It will be a class sign-up sheet, where you select which class you want to sign up for, the registration is recorded, and a seat is held for you at the time of the class. Some of the characters are coming into focus: the learner signing up for the class, the web application and a database. Undoubtedly, the use cases have already popped into your head; the stick figures and boxes are also a good start for a cast of characters.



In Figure 1, I have the cast of characters, represented by the vertical lines, sending arrows at each other; each arrow represents a message. The underlying protocols don't need to be modelled, at least at this level; we may come back to them later. For our purposes the medium that carries the arrows will make its best effort to deliver the message, and will often allow for a reply. We have three characters in our cast, represented by 3 vertical lines. We have two messages plus two reply messages, represented by the angling arrows.

The Angle of the Arrow ...

The angling arrows are pretty important in the representation. Anybody familiar with MSCs knows that synchronous operations have horizontal arrows, while asynchronous operations, ones off the clock, so to speak, have angling arrows. They angle because time passes differently between the actors sending and receiving the arrows; think Einsteinian relativity: from one observer's viewpoint a pair of events on another timeline might have occurred in a different order than another observer might see.

Whenever arrows angle like that, there is always the chance of arrows crossing; when arrows cross, conflicts occur, and when arrows cross at critical points, race conditions can occur. Our example in Figure 1 shows us 4 places where the arrows are angled. Each of those places is vulnerable to conflicts and race conditions. To do a good job in designing the application, you have to identify those conflicts and engineer solutions that prevent race conditions from occurring and handle conflicts in such a way that bad things don't happen.

Looking at Figure 1 some more, we see arrow 1, the request from the Learner to the Application. How can conflicts occur here? The most basic conflict is where the Learner conflicts with himself: pressing the Submit button twice will generate two reservations. In fact, the browser will close the first connection (making arrow 4 into an orphan) and, in fact, making the entire first transaction into an orphan. We can model this situation readily, as in Figure 2.


Simple web applications, where you have a web server that invokes applications, effectively as subroutines, will see each request from the browser and direct them to different instances of the web application. Each web application that is invoked, AppA and AppB, see an individual exchange with the Learner and try to satisfy it. AppA, not knowing that it has lost its connection with the Learner, will send message 2A to the Database where the class registration is made, returning via message 3A. When AppA tries to send the registration confirmation, message 4A, to the Learner, it finally discovers the closed connection and the confirmation is dropped on the floor.

Meanwhile, AppB has gone ahead, made a reservation, prepared the confirmation and has returned it to the Learner. We now have two copies of the reservation in the database, confusing student and teacher.

In this particular case, we didn't catch the conflict at all, until the teacher reviewing the reservations noticed the duplication. The teacher's annoyance with the web application continues to grow.

From Figure 2, we can see 3 places where the conflict could have been caught and dealt with, in various shades of courtesy. In fact, it is probably best if we could deal with the issue in all three places, but any one place will do for now.

Starting at the right side, with message 2 and response 3, we can see that if we have a proper database that does database-y things it can be set up to properly reject a duplicate reservation by the same person for the same class. It will be up to AppB to recognize that a duplicate was entered, and to provide a duplicate confirmation page to the Learner.

From the left side, we can presume we require a modern browser, and then we can "require" that Javascript be enabled on the browser in order to filter the redundant Submit button operation. This is often a weak and onerous requirement: some people won't know how to enable Javascript readily and in a safe manner; other people are strict about trusting sites. If the rest of your application does not require Javascript, it may not be practical to require it for this one operation.

In the middle, we would like the application itself to recognize when redundant requests occur. This is where the application server, if you have one, comes in, by supplying credentials on the Learner's browser that determine the web application instance and makes sure to route the submission to the correct application instance. Alternatively, supplying a transaction ID as a hidden field in the browser that is submitted with the button click might be enough to recognize the duplicated transaction. AppA and AppB from Figure 2 would merge but messages 1A, 1B and 2A would still be initiated. The application is then responsible for recognizing that it got 2 submissions, perhaps with identical content, and suppressing message 2B and somehow getting response 3A to present reservation confirmation 4B.

Conclusion

There are several other places where race conditions occur in our very simple application but I will leave them as an exercise for the reader. Here are the things I would like you to take away with you:

* Race conditions are a fact of life. Good software deals with all of the race conditions, at least to the point of recognizing when they occur. Some times all you can do is make sure to fail gracefully.

* The 3 points where you can deal with the example collision are the browser (suppressing multiple clicks), the web application (in an application server environment) and the database (presuming an ACID database is available). All of these solutions have to be included for comprehensive protection: in the browser to prevent accidental multiple-click submissions, in the application to at least report when a collision has occurred, and in the database to, once and for all, catch race conditions.

No comments:

Post a Comment