Introduction to Continuations

In this posting I am going to lay some of the groundwork for explaining what continuations are, why they are a ‘good thing’ and how .Net makes them easy.  Continuations are not new, they’ve been around for quite a while.  What is new is the ease by which they can be created and used in .Net, and what that ease of use means to SOA architecture design.

 

Before continuing, if you don’t know what continuations are, or only vaguely remember them from your CS class, I refer you to this excellent article on Wikipedia.  The article will give you a great introduction to them, as well as links to a number of general resources you can explore for more information.  For two simple examples of continuations in .Net, these articles, courtesy of Jason Halley, are interesting.  The conclusions the authors draw at the end are surprising, but no matter. I’ve drawn worse, as detailed below.

 

I must also observe that it wasn’t a period of reflection that caused me to realize that continuations were present in .Net, in fact I initially complained bitterly about the artifacts of their presence.  When I would serialize and deserialize a complex object with bound event handlers, these event handlers would cause me all sorts of problems.  Especially painful was the implementation of framework code that was forced to deal with event handlers it didn’t know anything about bound to objects it also didn’t know anything about, yet was expected to handle in a reasonable fashion. 

 

As I grew to understand the value of domains, I gained more appreciation for the artifact that made continuations possible, but I still didn’t see the light.  The artifact that I’m speaking of is the ability to serialize a delegate, and even more specifically, the ability to serialize both the delegate and the serializable object instance it is attached to, when this is the case.  With the arrival of .Net 2.0 I became very excited about what closures would bring to the table, yet still didn’t see the light regarding serializable events.

 

Then I read Essential Windows Workflow Foundation by Dharma Shukla and Bob Schmidt.  If you haven’t read this book, and plan on using Windows Workflow Foundation (WF), and you want to understand what’s goint on under the covers, I can’t recommend this book enough.  In the context of this article, it was the very first chapter that caused the scales to fall away from my eyes.  I must admit to a certain amount of chagrin, it feels to me that the unspoken part of WF’s name is ‘Hey, Stupid!’.

 

Continuations are the fundamental mechanism at the core of WF.  This isn’t to say that if you implement continuations directly you won’t need WF, rather that the core technique that makes workflow possible does not itself require workflow, instead, it is what enables workflow.  This technique can be used to great advantage without using workflow, which is what the next series of posts will concentrate on.

 

Consider the lifecycle of the average system or subsystem in the middle tier of an enterprise application.  A large amount of it’s time is spent doing nothing.  Even in an enterprise app that is considered heavily loaded, the application is probably spending a few hours a day doing little or nothing.  May elements of enterprise middleware are even more idle, laying about in system memory, issuing brief series of requests to other services, or responding to requests, and then going back to dreaming of electric sheep.

 

The rub is, that whether or not the application is actively doing something, or waiting for some external entity to fulfill a request, the burden is on the application to ensure it maintains an operational state at all times.  For SOA enterprise applications employing direct messaging between services, if a request is sent to a foreign system, two things hold.  The foreign system must be running in order to receive the request, and the originating system must stay running until the response is received.  Messaging middleware such as MSMQ or MQ can be used to relax this restriction, but these are complex systems in their own right, and there is a significant cost to deploying and using the messaging middleware. 

 

I’m not knocking these systems, they have great value.  I am, however, observing that when such systems are used to address the two problems I mentioned above, a very high price is being paid simply to make systems that aren’t actually doing anything reliable.  What I want to do is show you how continuations can be used to gain this exact advantage without the need to use messaging middleware.  Please don’t take this to mean I think you should throw such middleware out, only that I think there are better things for this middleware to do, and that this capability can be used at more places in your systems than the exact points of message exchange.  Not to mention the fact that in a large SOA system which might communicate with services outside the organization, the external services might not be using such middleware.

 

Specifically, you can create continuations in .Net by using delegates bound to serializable object instances that carry the data you wish to preserve across separate invocations of your applications.  Persisting these continuations to a durable centrally available store such as a database gives your SOA application thread, domain, process, and machine agility. You could begin processing a complex message transaction on one machine and complete processing it on another, changing thread, domain, process, and machine, without a single hiccup in your internal operations.

 

The strategic result of this is that you no longer need to be concerned with preserving the operating state of your system when it isn’t actively performing some task.  In any situation where your system is waiting for any combination or number of service requests  or responses to be received from other services, you can use continuations to make it possible to stop and restart your system.  Because your system is capable of stopping and restarting, in fact capable of restarting on any machine with equivalent resources and with access to the persisted continuation data, the reliability demands placed on it are considerably relaxed.

 

For enterprise developers this is the true benefit of continuations.  They significantly relax the demands on operational reliability;

  • A Service must be reliable when it is executing the core logic of a service.
  • A Service must be reliable until it has recorded the continuation representing its call on an external service.
  •  A Service that is simply waiting for requests or responses does not need to be reliable.

 

In the next chapter, we’ll go into a mechanism that can be used to implement support for continuations, adapted from X, that I mentioned above.  Once we have the framework in hand, we’ll begin exploring how this capability changes the requirements on our architecture,
Published Monday, April 09, 2007 9:01 PM by MarkMMullin
Filed Under: ,

Comments