Monday, June 7, 2010

Handling WCF TimeoutExceptions "Globally" Part 1

One of the WCF services I've setup at work has a high volume of calls being made through it. The application retrieving this information requires the data to be delivered in a timely fashion and we can't afford there to be timeouts.

Most of the methods have been split out onto separate WCF service instances to better configure their InstanceContextMode and ConcurrencyMode so that we may handle the priority of the importance of the data as well as handling caching.

Due to some clients being many network hops away, we would get random timeouts that we weren't able to control. In addition, sometimes there were high cost (webserver-side, not database) methods and resource consumption would spike causing a temporary queue for data.

I wanted to handle time-outs without having to muck-up my code by putting a try catch around everything. Also since i had split different methods onto different WCF service instances i had multiple clients. So if i made a change in the proxy, i'd have to make it in more than one place, which is bad news for code upkeep.

My solution was to make use of Generic Methods and Service Extensions to create a wrapper of sorts to handle my service calls.

namespace SecretProject.Module.Services
{
    public static class ExceptionService
    {
        public static T TryWebMethod<T, TClient>(this TClient client, string methodName,params object[] parameters)
        {
            try
            {
                    MethodInfo methodInfo = client.GetType().GetMethod(methodName);
                    return (T) methodInfo.Invoke(client, parameters);
            }
            catch (Exception err)
            {
                if (err.InnerException is TimeoutException)
                {

                }
            }
            return default(T);
        }
    }
}

The above code would allow me to call the method and handle globally the TimeOutException, if thrown.

In this example, assume the GetProgrammers, from dataClient (of type CommonServiceClient), returns a List of the class Programmers
This would change my usage of the method from something like:

dataClient.GetProgrammers(parameter1, paramter2);


To this:

dataClient.TryWebMethod<List<Programmers>,CommonServiceClient>("GetProgrammers",parameter1, paramter2);

This allows us to now handle logging, rolling over to a backup server, requiring user interaction to make another attempt, or whatever you may want to handle here! And this will all be done without having to muck-up your code around every service call.

In Part 2, I will show how I handle rolling over to a backup server to temporarily balance the "overflow of the data queue" on that one server.

No comments :