Recently I’ve been working on a RESTful HTTP server in WCF for a really cool project that isn’t public yet, but should be soon. I say RESTful, but it’s not religiously so; more accurately its REST-like. Essentially it’s as basic as can be so that client compatibility can be maximized. Anyway, the need was presented that client would have to recieve notifications for certain events, and we were wary of letting thousands (tens/hundreds of thousands we hope?) of clients continuously poll the server for those status updates. We looked into server push techniques, and of course there’s no “standard” way of doing things. While we plan to include some vendor-specific technologies eventually into the server we decided to go with Long Polling as a fall-back for clients that can’t handle those specifics. Long polling is a technique where a client sends a normal request to the server, but the server does not return a response until successful data is available, which could be a long time. You also usually include a timeout to this request to keep the connections from getting too stale. The client takes a timeout as a signal to just make another request and wait longer. In whole the process works like this:
Server
- Recieve Request
- Wait (usually on another thread) for data to become available (ex: an object reaches a certain status)
- Return Response
Client
- Send Request
- Wait for reply (usually on another thread)
- If we get back a timeout error simply restart the process
- If we get back a valid response this is our “notification”
Doing this in WCF is actually pretty easy. WCF has the ability to use an “asynchronous pattern” on operation contract methods, which means that the message handling thread can go and handle other requests while your waiting thread does the work. Once your work thread finishes a service method picks things back up and returns the response to the client. This page does a good job of explaining the particulars, so I won’t repeat them here. It’s pretty simple to setup on the server side, anyway:
[OperationContract]
public string GetNotification();
turns into
[OperationContract(UseAsyncPattern = true)]
public IAsyncResult BeginWaitNotification(AsyncCallback callback, object state);
public string EndWaitNotification(IAsyncResult result);
You now need two methods, one starting with “Begin” and the other with “End”. The begin method is responsible for returning an IAsyncResult implementation, which is passed to the end method once it completes; the end method being responsible for returning the result to the client. Attached to this blog post is an abstract base class that implements IAsyncResult and provides timeout mechanisms and such. To use it you would define your strongly-typed async result:
public class MyNotificationResult : LongPollingAsyncResult
{
//constructors, etc
protected override DoWork()
{
//here we actually check for any notifications, if we have result we call base.Complete(...)
}
}
And then in your service methods use it like so:
public IAsyncResult BeginWaitNotification(AsyncCallback callback, object state)
{
return new MyNotificationResult(callback, state);
}
public string EndWaitNotification(IAsyncResult result)
{
MyNotificationResult myResult = result as MyNotificationResult;
if(myResult == null)
throw new ArgumentException("result was of the wrong type!");
myResult.WaitForResult();
return myResult.Result;
}
And there you have it! Clients can now use long polling against the WaitNotification operation. In future posts I’ll expand on the idea and analyze the implementation’s behavior more, but for right now I’m just happy that WCF allows long polling in a relatively elegant way.
henji wo matte kudasaine!