As many of us deploy our shiny web services and expose them to the world (or just our apps), we invariably encounter these pesky maintenance windows. During these times, a database, other web services or any other IO dependent tasks cannot be performed.
Wouldn’t it be nice to tell the caller of your web API that the operation is currently unavailable? It can get pretty ugly if we don’t solve this. If we simply bring down the whole endpoint, connecting clients will experience a pile-up of timed out connection attempts. If we leave it up, every operation attempted would experience it’s own slow excruciating failure, with the same IO timeout pile-up, this time on your server and often bringing the server to it’s knees with too many doomed connection requests queued up. My game plan shaped up to :
- Each service operation shall return a standard response, exposing some status flag
- A configuration controls whether services are to be marked as unavailable
- A WFC extension will take care of returning the standard response with proper flag when so configured, but let the regular response return under normal conditions.
The requirement that each operation returns a standard response may seem peculiar. You may have created
string GetUserName(string id);
The thing is, when operations fail, you have no way to signal the caller except for smelly nulls or throwing exceptions. Although Soap Fault Exception can do the trick, I find it distasteful to throw a Client Fault exception because exceptions are more costly, and validation of request data often enough finds client faults. For that and other reasons, I use code that looks like the following:
Where the status is an enumeration:
One may also abstract the ServiceResponse to an interface, allowing any response object to implement the interface rather than inherit the base response. For this post, let’s just go with the base class.
Now the signature of every operation would be an object derived from ServiceResponse. Rather than a fragmented GetName, GetBirthdate etc – a chatty interface anyway – we would expose:
public class GetUserResponse: ServiceResponse
Now that we have that out of the way, you get the payoff: we can define a fail fast attribute to decorate operations we know rely on some back-end which may be turned off on us. We’ll utilize the IOperationBehavior extension point of WCF, allowing us to specify behavior on an operation by operation basis.
I’ve created an attribute implementing the IOperationBehavior. It replaces the operation invoker with my own implementation when ApplyDispatchBehavior is called. All other IOperationBehavior methods remain blank.
public class FailFastOperationAttribute : Attribute, IOperationBehavior
The finishing piece is to implement the operation invoker. It will check a special configuration, and based on that would either invoke the underlying operation as the stock implementation would have, or construct a new response with the failed flags set.
public class FailFastOperationInvoker : IOperationInvoker
A method for determining if the API should by up or down hides behind the
Config.ShouldFailFast() call. Read your app setting, check a file, do what you like to make that determination.
The next thing is manufacturing an instance of a response object. Here we need to create the same type or a type assignable to the one the formal method expected. Note that that type would need to have a parameter-less constructor for this to work. Since all my service DTO are plain POCO, this is rarely a restriction.
With this code in place, all we need to do is decorate specific methods as
[FailFastOperation] and bingo!