The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

Archive for the 'agatha' Category

Securing Your Agatha Service Layer

Posted by Davy Brion on 27th January 2010

The question of how to implement security for an Agatha Service Layer is one that comes up frequently.  First of all, you need to remember that if you’re using Agatha with WCF you can use any of the WCF features that you’d normally use to secure your WCF service.  There’s already plenty of information available online or in books on implementing security for WCF services so i’m not going to spend time on covering those options.  What i am going to cover is the approach that we typically use for our Agatha service layers.

I don’t like to tie myself to WCF-specific features, so i always plug in custom authentication into either a custom Request Processor, or a base Request Handler class that all other Request Handlers must inherit from.   But first, how do we get the authentication-related data from the client to the service?

In each project i use Agatha in, i always have a MyProjectRequest and MyProjectResponse base class:

    public class MyProjectRequest : Request

    {

        public string UserName { get; set; }

        public byte[] PasswordHash { get; set; }

    }

 

    public class MyProjectResponse : Response {}

 

Each request in the project inherits from this base request, and each response inherits from the base response.  The base response class is often empty, though this does make it very easy if you ever need to send something back with every response.

Now obviously, if every single request that is sent to your service layer needs values for the UserName and PasswordHash properties you want this to be done in only one place.  I do this by using a custom request dispatcher:

    public class MyProjectAsyncRequestDispatcher : AsyncRequestDispatcher

    {

        private readonly IUserContext userContext;

 

        public MyProjectAsyncRequestDispatcher(IAsyncRequestProcessor requestProcessor, IUserContext userContext) : base(requestProcessor)

        {

            this.userContext = userContext;

        }

 

        protected override void BeforeSendingRequests(IEnumerable<Request> requestsToProcess)

        {

            base.BeforeSendingRequests(requestsToProcess);

 

            foreach (var myProjectRequest in requestsToProcess.OfType<MyProjectRequest>())

            {

                myProjectRequest.UserName = userContext.UserName;

                myProjectRequest.PasswordHash = userContext.PasswordHash;

            }

        }

    }

 

The IUserContext dependency is just a component that is registered in my IOC container and will be injected automatically whenever you get an instance of IAsyncRequestDispatcher.   Now, in this example you can see that i add the authentication data to every request in a batch, even though the batch will be sent in one roundtrip.  If you want, you can add the authentication data only to the first request and then only use the first request to do the authentication within your service layer.  I prefer to add the authentication data to each request and then authenticate every single request (even subsequent requests in a batch) within the service layer.  I’ll get back to this point later on.

Now, the only thing we need to do to make sure that your requests will always have the authentication data contained within them is to instruct Agatha to always use instances of your MyProjectAsyncRequestDispatcher class whenever an IAsyncRequestDispatcher is needed.  This is easily done during Agatha’s client-side configuration:

            new ClientConfiguration(typeof(MyProjectRequest).Assembly, new Agatha.Castle.Container(myContainerWrapper))

                {

                    AsyncRequestDispatcherImplementation = typeof(MyProjectAsyncRequestDispatcher)

                }

                .Initialize();

 

Keep in mind that you still have to register your IUserContext with the container on your own though. 

With that in place, we are sure that each request that comes from our clients always contains the proper authentication data.  Now we need to make sure that we actually authenticate these requests within the service layer.  You basically have 2 options: either implement your own Request Processor which adds authentication checks, or create a base Request Handler that your other Request Handlers inherit from.

We’ll first cover the option of using a custom Request Processor.   You could create one like this:

    public class MyProjectRequestProcessor : RequestProcessor

    {

        private readonly IAuthenticator authenticator;

 

        public MyProjectRequestProcessor(IAuthenticator authenticator, ServiceLayerConfiguration serviceLayerConfiguration, ICacheManager cacheManager)

            : base(serviceLayerConfiguration, cacheManager)

        {

            this.authenticator = authenticator;

        }

 

        protected override void BeforeHandle(Request request)

        {

            var myProjectRequest = request as MyProjectRequest;

 

            if (myProjectRequest != null)

            {

                if (!authenticator.AreValidCredentials(myProjectRequest.UserName, myProjectRequest.PasswordHash))

                {

                    throw new MySecurityException();

                }

            }

        }

    }

 

The BeforeHandle virtual method is called right before the request is passed to its Request Handler to be handled.  Note that this Request Processor would authenticate every request.  If you want a Request Processor that only authenticates the first request, you could do so like this:

    public class MyProjectRequestProcessor : RequestProcessor

    {

        private readonly IAuthenticator authenticator;

 

        public MyProjectRequestProcessor(IAuthenticator authenticator, ServiceLayerConfiguration serviceLayerConfiguration, ICacheManager cacheManager)

            : base(serviceLayerConfiguration, cacheManager)

        {

            this.authenticator = authenticator;

        }

 

        protected override void BeforeProcessing(IEnumerable<Request> requests)

        {

            var myProjectRequest = (MyProjectRequest)requests.ElementAt(0);

 

            if (!authenticator.AreValidCredentials(myProjectRequest.UserName, myProjectRequest.PasswordHash))

            {

                throw new MySecurityException();

            }

        }

    }

 

The BeforeProcessing virtual method is called before any of the requests are handled, so you could authenticate only the first request in a batch and then proceed with regular processing if the first one is authenticated.  Now, the big problem that i have with this approach is that you aren’t really in control of what is sent to your service layer.  Yes, you can guarantee that each request coming from your clients contains the proper authentication data.  What you simply can’t guarantee however is what other people or custom clients can send to your service layer.  If they send you a batch of 2 requests, the first containing valid credentials of a normal user for a benign request, it will pass the authentication just fine.  If the second request in that batch contains invalid credentials (to trick your authorization into believing it’s from a user with higher privileges for instance) for a request that could cause some damage (deleting important information or triggering certain tasks or whatever), then you can’t really do anything to prevent that.  Unless of course, you reject this approach and authenticate every single request.

As for the MySecurityException type, that’s up to you as well.  When you configure your Agatha service layer, you can set the SecurityExceptionType property to the type of exception that should be considered as a security exception.  When the Request Processor catches an exception of that type, it will set the ExceptionType property of the response to ExceptionType.Security so you can check for that specific situation in your client.

To configure Agatha to use your custom Request Processor, your configuration code would look like this:

            new ServiceLayerConfiguration(Assembly.GetExecutingAssembly(), typeof(MyProjectRequest).Assembly,

                new Agatha.Castle.Container(containerWrapper))

                {

                    RequestProcessorImplementation = typeof(MyProjectRequestProcessor),

                    SecurityExceptionType = typeof(MySecurityException)

                }

                .Initialize();

 

Another alternative is to create a base Request Handler for your project and to have each Request Handler inherit from it.  Something like this, for instance:

    public abstract class MyProjectRequestHandler<TRequest, TResponse> : RequestHandler<TRequest, TResponse>

        where TRequest : MyProjectRequest

    {

        public IAuthenticator Authenticator { get; set; }

 

        public override void BeforeHandle(TRequest request)

        {

            base.BeforeHandle(request);

 

            if (!Authenticator.AreValidCredentials(request.UserName, request.PasswordHash))

            {

                throw new MySecurityException();

            }

 

            Authorize(request);

        }

 

        protected virtual void Authorize(TRequest request) {}

    }

 

In case you’re wondering why i’m using Setter-injection here instead of Constructor-injection, read this.

I typically prefer the custom Request Handler approach for authentication.  In most applications that we write, authentication is not enough and we need custom authorization checks for many requests.  So i’m going to need a base Request Handler which introduces the virtual Authorize method anyway.  So i might as well do my authentication check right before it.

With the custom Request Handler approach, you probably still want to configure Agatha to use your custom security exception type:

            new ServiceLayerConfiguration(Assembly.GetExecutingAssembly(), typeof(MyProjectRequest).Assembly,

                new Agatha.Castle.Container(containerWrapper))

                {

                    SecurityExceptionType = typeof(MySecurityException)

                }

                .Initialize();

 

And then you just need to let your own Request Handlers inherit from your MyProjectRequestHandler.  Authentication will be performed for each request by default, and you can easily add specific authorization logic for every request. 

And those are pretty much the options you have to secure your Agatha Service Layer.   Oh, and be sure to only expose your Service Layer through SSL :)

Posted in agatha | 4 Comments »

Agatha Vs NServiceBus?

Posted by Davy Brion on 26th January 2010

Ever since i open sourced Agatha, i’ve gotten questions from people who are wondering whether they should use Agatha or NServiceBus.  I’ve also gotten questions about things that people wanted to do with Agatha but that aren’t really supported.  And i’ve also noticed that people were coming to my site with search keywords like “agatha vs nservicebus”.  The thing is, they are hardly comparable.

Agatha is a Request/Response Service Layer framework.  It basically supports synchronous and asynchronous Request/Response style communication and tries to make it as easy as possible to write a service layer for that type of communication.  Apart from being easy to use, it also encourages a clean implementation of your service layer and a way to minimize the repetitiveness of cross-cutting concerns.  It also enables you to get better performance than with typical Remote Procedure Call or Remote Method Invocation style service layers because it will try to minimize roundtrips by batching requests and responses together.  In the next release, it will also offer a caching layer so certain requests (depending on how you set it up) don’t need to be processed and cached responses can simply be returned.  There’s also support for one-way requests (or fire-and-forget requests) but it has the same downsides as one-way requests with typical WCF services have. That’s pretty much all it does.  That’s probably all it’ll ever do.  In short, it’s just an upgrade over your typical WCF services.

NServiceBus on the other hand also does Request/Response, but that’s just one of the things it can do.  Again, Agatha is essentially an RPC or RMI framework whereas NServiceBus is built on top of one-way messaging technology.  This allows for much more possibilities when it comes to communicating between different applications or different parts or processes within the same application boundary.  A great overview of those possibilities can be found here.  Because it is based on messaging, there are a lot of benefits that you can get from NServiceBus that you’ll probably never get from Agatha.  For one, the ‘Store & Forward’ messaging model from NServiceBus might seem similar to Agatha’s one-way requests on first sight, but there are some very important differences.  If you send a fire-and-forget request with Agatha, and the service is currently down, then that request is essentially lost.  With NServiceBus, the message is stored in a message queue and it will be processed when the target of the fire-and-forget message comes up again.  From a reliability point of view, that’s obviously a tremendous improvement over what Agatha can offer you.  Another area where NServiceBus truly shines (IMO) is in its Publish/Subscribe implementation.  Some people have asked me if i’ll ever provide something like that in Agatha and the answer has always been ‘no’.   For one, it doesn’t fit into what Agatha tries to do and i don’t see the point in implementing it if a better implementation is available already in another project.   There’s plenty more interesting things in NServiceBus to deal with more advanced scenarios, which you’ll have to find out about on your own ;)

So which one is more suitable for you or your applications? As with every technology choice, it depends.  Agatha is great for most typical business applications.  If you need to communicate between one or more different clients (with different i don’t mean multiple instances but different types of clients like a web app, a silverlight client and/or a WPF client) and one service (you can obviously use it with more than one service as well if you want to) on an application server which encapsulates your business layer then it is a very attractive solution, as long as you don’t need the superior reliability that NServiceBus can offer you.  With superior reliability i particularly mean the ability to still process received messages once the service layer comes back up after having been unavailable.  In my experience, most business applications don’t really need that, since most of those applications are entirely unusable if the service they depend on is down.  In short, if all the possible downsides of using a WCF service layer are not an issue for your project, then Agatha will be a great fit.

If however, you need to maximize reliability, performance and general robustness of a critical enterprise application, then NServiceBus will definitely be a much better choice.  If you’re dealing with many distributed parts, NServiceBus will also make things much easier for you than Agatha (or any other WCF service layer for that matter) will.   And obviously, if you want to integrate multiple applications while reducing coupling between applications as much as possible, NServiceBus will also be a much better fit than Agatha.  With NServiceBus, you’d only need to share an assembly containing the types of the messages.  With Agatha, you either need to share an assembly with shared request/response types or use proxies for them and you would also have to know about the other applications since you’d need to access their services directly.  This can get quite ugly pretty fast.

And in some cases, you can just use both of them at the same time.  At work we have two projects that use Agatha for all of their internal communication within their own application boundary, yet they use NServiceBus to notify each other of certain events.  Neither of the applications knows about the existence of the other… the only thing they share is one assembly with some shared message types.  We’ve also started working on a new platform where each application in the platform will use Agatha for all of the communication within their own application boundary (since they’re all typical silverlight clients backed by a WCF service style applications) but they will use NServiceBus for every kind of communication that goes outside of the application boundary.

As with many things, it’s just a matter of choosing the right tool for the right job.  Hopefully, this post will help some of you make that decision should you need to make it in the future :)

Posted in agatha, nservicebus | 8 Comments »

Testing Agatha’s Caching Functionality With QuickNet

Posted by Davy Brion on 24th December 2009

In this post i’m going to give you a very detailed explanation of a QuickNet test that i wrote for Agatha’s caching layer.  If i do my job well, you’ll have a much better view on what QuickNet does, how it works, and how it can help you.  I do want to ask you to keep a very open mind and to forget pretty much everything that you know about automated testing, including your opinions on what should or should not be done in an automated test.  If you have problems with that, you might be interested in more conservative reading on automated testing.  Still here? Alright, let’s get started.  Please stay focused throughout, because you will need it :p

First of all, requests whose response is eligible for caching must override the Equals method and the GetHashCode method.  I’ll use the following two request/response combinations for this test:

    [EnableResponseCaching(Seconds = 1)]

    public class FirstCachedRequest : Request

    {

        public string String { get; set; }

 

        public bool Equals(FirstCachedRequest other)

        {

            if (ReferenceEquals(null, other)) return false;

            if (ReferenceEquals(this, other)) return true;

            return Equals(other.String, String);

        }

 

        public override bool Equals(object obj)

        {

            if (ReferenceEquals(null, obj)) return false;

            if (ReferenceEquals(this, obj)) return true;

            if (obj.GetType() != typeof(FirstCachedRequest)) return false;

            return Equals((FirstCachedRequest)obj);

        }

 

        public override int GetHashCode()

        {

            return (String != null ? String.GetHashCode() : 0);

        }

    }

 

    public class FirstCachedResponse : Response { }

 

    [EnableResponseCaching(Seconds = 2)]

    public class SecondCachedRequest : Request

    {

        public int Integer { get; set; }

 

        public bool Equals(SecondCachedRequest other)

        {

            if (ReferenceEquals(null, other)) return false;

            if (ReferenceEquals(this, other)) return true;

            return other.Integer == Integer;

        }

 

        public override bool Equals(object obj)

        {

            if (ReferenceEquals(null, obj)) return false;

            if (ReferenceEquals(this, obj)) return true;

            if (obj.GetType() != typeof(SecondCachedRequest)) return false;

            return Equals((SecondCachedRequest)obj);

        }

 

        public override int GetHashCode()

        {

            return Integer;

        }

    }

 

    public class SecondCachedResponse : Response {}

 

Agatha’s Request Processor should cache responses for requests that are eligible for caching, and when subsequent requests need to be processed which are equal (in their values) to previous requests whose response has been cached already, the cached response needs to be returned instead of handling the request again.

In order to inspect the usage of the caching layer during tests, i wrote the following CacheManagerSpy class which inherits from my normal CacheManager class (which is used by Agatha):

    public class CacheManagerSpy : CacheManager

    {

        private List<CacheEntry> cacheEntries;

        private List<Response> returnedCachedResponses;

 

        public IEnumerable<CacheEntry> CacheEntries

        {

            get { return cacheEntries; }

        }

 

        public IEnumerable<Response> ReturnedCachedResponses

        {

            get { return returnedCachedResponses; }

        }

 

        public CacheManagerSpy(CacheConfiguration configuration, ICacheProvider cacheProvider) : base(configuration, cacheProvider)

        {

            Clear();

        }

 

        public void Clear()

        {

            cacheEntries = new List<CacheEntry>();

            returnedCachedResponses = new List<Response>();

        }

 

        protected override Response GetCachedResponseFor(Request request, string region)

        {

            var cachedResponse = base.GetCachedResponseFor(request, region);

            returnedCachedResponses.Add(cachedResponse);

            return cachedResponse;

        }

 

        protected override void StoreInCache(Request request, Response response, TimeSpan expiration, string region)

        {

            cacheEntries.Add(new CacheEntry(request, response, expiration, region));

            base.StoreInCache(request, response, expiration, region);

        }

 

        public class CacheEntry

        {

            public Request Request { get; private set; }

            public Response Response { get; private set; }

            public TimeSpan Expiration { get; private set; }

            public string Region { get; private set; }

 

            public CacheEntry(Request request, Response response, TimeSpan expiration, string region)

            {

                Request = request;

                Response = response;

                Expiration = expiration;

                Region = region;

            }

        }

    }

 

This Spy basically gives me the ability to see which entries are stored in the cache, and which responses have been returned.

Now i can create a QuickNet Acid test.  I’m going to go over the code step by step instead of listing it all at once because each step probably needs quite a bit of explanation if you don’t understand QuickNet yet.

First of all, here’s the definition of the test:

    public class RequestProcessorCachingSpecs : AcidTest

    {

        public RequestProcessorCachingSpecs() : base(10, 2000) { }

 

The 10 means that QuickNet will perform 10 testruns.  The 2000 means that each testrun will contain 2000 executions of the defined transitions.  Don’t worry yet about what a transition is, i’ll get to that later on in the post.

We’ll also need some fields to access some of the classes that will be used in this test:

        protected static IRequestHandler<FirstCachedRequest> firstCachedRequestHandler;

        protected static IRequestHandler<SecondCachedRequest> secondCachedRequestHandler;

        protected static IRequestProcessor requestProcessor;

        protected static CacheManagerSpy cacheManager;

 

Yeah, i know what you’re thinking.  Static is bad right?  Well, not in this case since we need to be able to use these instances in some inner classes that we’ll go over soon enough and these references will hold the same instance for each testrun (which, as mentioned consists of 2000 transition executions).  Anyway, forget about the static keyword for a second and keep reading.

Now we can implement the SetUp of our testrun:

        public override void SetUp()

        {

            IoC.Container = new Agatha.Castle.Container();

 

            var serviceLayerConfiguration = new ServiceLayerConfiguration(Assembly.GetExecutingAssembly(),

                Assembly.GetExecutingAssembly(), IoC.Container)

            {

                BusinessExceptionType = typeof(BusinessException),

                SecurityExceptionType = typeof(SecurityException),

                CacheManagerImplementation = typeof(CacheManagerSpy)

            };

            serviceLayerConfiguration.Initialize();

 

            // i want to take advantage of the automatic initialization, so i’m just resolving the requestprocessor instead of creating it

            requestProcessor = IoC.Container.Resolve<IRequestProcessor>();

            // the cache manager is a singleton so i can just resolve it and it’ll be the same one the request processor uses

            cacheManager = (CacheManagerSpy)IoC.Container.Resolve<ICacheManager>();

 

            firstCachedRequestHandler = MockRepository.GenerateMock<IRequestHandler<FirstCachedRequest>>();

            secondCachedRequestHandler = MockRepository.GenerateMock<IRequestHandler<SecondCachedRequest>>();

 

            IoC.Container.RegisterInstance(firstCachedRequestHandler);

            IoC.Container.RegisterInstance(secondCachedRequestHandler);

        }

 

This setup code will be executed for each testrun.  So QuickNet will execute this 10 times, and each time it will run 2000 transition executions on the classes that we set up for the current testrun. 

So what exactly is a transition? It’s just a piece of code that you want to execute.  That piece of code can receive input and it can return output.  It’s basically the code that you’re testing.  Our transition will simply consist of calling Agatha’s Request Processor and instructing it to process 2 requests.  Those requests would be the two request types shown earlier which are eligible for caching.  After QuickNet executes the transition, it will also verify that our defined specifications for that particular transition are indeed correct.

Let’s define the input that our transition will receive.  In this particular case, we need a Request instance, an instance of a Request Handler for that Request, and the Response that the Request Handler needs to return if there’s no valid Response available in the cache.  So we’ll use the following helper class to define this input:

        public class ProcessInputElement

        {

            public IRequestHandler RequestHandler { get; private set; }

            public Request Request { get; private set; }

            public Response Response { get; private set; }

 

            public bool RequestHandlerWasExecuted { get; private set; }

 

            public ProcessInputElement(IRequestHandler requestHandler, Request request, Response response)

            {

                RequestHandler = requestHandler;

                Request = request;

                Response = response;

            }

 

            public void StubHandler()

            {

                RequestHandler

                    .Stub(r => r.Handle(Arg<Request>.Is.Same(Request))) // WHY: reference check iso equality check

                    .Return(Response)

                    .WhenCalled(a => RequestHandlerWasExecuted = true)

                    .Repeat.Once();

            }

        }

 

An instance of this class basically combines the Request, its Request Handler and the Response that needs to be returned.  It also contains a helper method so we can easily instruct the mocked Request Handler to return the given Response when it is asked to handle the given Request.  And we’ll also set a simple flag to true if the Request Handler has indeed been called.

As i mentioned a few times already, QuickNet will execute our transition (which i’ll show later on in the post) 2000 times for each testrun.  Obviously, we can’t be expected to create these instances manually all the time, so we need to define some generators that QuickNet will be able to use to randomly generate the input that it can pass to the transition.  We first need two generators which are capable of generating random instances of the FirstCachedRequest and SecondCachedRequest types:

        public class FirstRequestGenerator : BaseGenerator<FirstCachedRequest>

        {

            public FirstRequestGenerator()

            {

                AddGeneratorForProperty(r => r.String, new StringGenerator(1, 1)); // generates a random string of 1 character

            }

        }

 

        public class SecondRequestGenerator : BaseGenerator<SecondCachedRequest>

        {

            public SecondRequestGenerator()

            {

                AddGeneratorForProperty(r => r.Integer, new IntGenerator(0, 5));

            }

        }

 

The FirstRequestGenerator class is capable of returning a new instance of FirstCachedRequest whenever it is asked to do so, and it will populate the FirstCachedRequest instance’s String property with a random string consisting of one character.   Some of the generated instances will be considered equals of each other if the generated string value is equal, and some will not be considered as equals if the generated string value is not equal.  The SecondRequestGenerator basically does the same thing, except that it will populate the SecondCachedRequest instances’ Integer property with a random int value between 0 and 5.  So again, some of the generated instances will be considered as equals, and some won’t.   The important part to remember is that QuickNet will generate random instances for us and that we don’t have to worry about it.

Now that we have the generators for the request instances, we can write a generator which can generate random ProcessInputElement instances:

        public class ProcessInputTupleGenerator : BaseGenerator<Tuple<ProcessInputElement, ProcessInputElement>>

        {

            private FirstRequestGenerator firstRequestGenerator = new FirstRequestGenerator();

            private SecondRequestGenerator secondRequestGenerator = new SecondRequestGenerator();

 

            protected override Tuple<ProcessInputElement, ProcessInputElement> GetDefaultInstance()

            {

                var firstElement = new ProcessInputElement(firstCachedRequestHandler, firstRequestGenerator.GetRandomValue(),

                                                           new FirstCachedResponse());

                var secondElement = new ProcessInputElement(secondCachedRequestHandler, secondRequestGenerator.GetRandomValue(),

                                                            new SecondCachedResponse());

 

                return Tuple.New(firstElement, secondElement);

            }

        }

 

Actually, this generator doesn’t just generate one instance of ProcessInputElement, it generates a tuple consisting of two ProcessInputElement instances.  The first value in the tuple will always contain a random instance of FirstCachedRequest, its Request Handler and a FirstCachedResponse instance that needs to be returned by the Request Handler if there’s no cached response yet.  The same goes for the second value in the tuple, except that it has a random instance of SecondCachedRequest, its Request Handler and a SecondCachedResponse instance.

Again, every time QuickNet will execute our transition, it will ask the ProcessInputTupleGenerator to generate a new tuple, and that tuple will contain the random request instances.  The generated tuple is then passed into the transition and the transition will be executed.

Now i can finally show you the transition that we’ll define:

        public class ProcessRequestsTransition : MetaTransition<Tuple<ProcessInputElement, ProcessInputElement>, Response[]>

        {

            public ProcessRequestsTransition()

            {

                Generator = new ProcessInputTupleGenerator();

                Execute =

                    input =>

                        {

                            cacheManager.Clear(); // clears the spy for every execution of this transition

 

                            input.First.StubHandler();

                            input.Second.StubHandler();

 

                            return requestProcessor.Process(new[] {input.First.Request, input.Second.Request});

                        };

            }

        }

 

As you can see, the ProcessRequestsTransition inherits from the MetaTransition<TInput, TOutput> class.  So we basically just defined that the input of the transition is a Tuple<ProcessInputElement, ProcessInputElement> and the output is an array of Response objects.  In the constructor of the transition, we define that the generator to be used to generate the input values is the ProcessInputTupleGenerator.  And we also define what actually needs to be executed by the transition.  In this case, the piece of code that will always be executed will first clear the CacheManagerSpy instance (so we can safely inspect it during our specification verification), it will then prepare both Request Handler mocks and then it simply calls the Process method of the Request Processor.  It’s output (a Response array) will be the output of the transition since that is our return value.

After all that work, we can finally define our specifications for this transition.  Let’s start with the first one:

        [SpecFor(typeof(ProcessRequestsTransition))]

        public Spec ResponsesAreCachedIfTheyArentInTheCacheYet(Tuple<ProcessInputElement, ProcessInputElement> input, Response[] output)

        {

            return new Spec(() =>

                    {

                        Action<ProcessInputElement> verify =

                            element =>

                                {

                                    Ensure.Equal(element.Response, cacheManager.CacheEntries.First(e => e.Request.Equals(element.Request)).Response);

                                    Ensure.True(output.Contains(element.Response));

                                    Ensure.True(element.RequestHandlerWasExecuted);

                                };

 

                        if (cacheManager.CacheEntries.Any(e => e.Request.Equals(input.First.Request)))

                        {

                            verify(input.First);

                        }

 

                        if (cacheManager.CacheEntries.Any(e => e.Request.Equals(input.Second.Request)))

                        {

                            verify(input.Second);

                        }

                    })

                .IfAfter(() => cacheManager.ReturnedCachedResponses.Any(r => r == null));

        }

 

The SpecFor attribute makes it possible to define which Transition this Spec belongs to.  The method has 2 parameters, which correspond with the input that will be passed into the transition, and the output that the transition returned.  It’s very important to realize that this method is executed before the transition is executed (yet after the input has been generated), but the block of code that we pass into the Spec instance will only be executed after the transition has been executed.  Actually, that block of code will only be executed if the Spec’s precondition and postcondition have been satisfied.  The precondition (which can be defined with the Spec class’ If method) will be evaluated before the transition is executed.  If it evaluates to false, the spec will be ignored for the current execution of the transition.  The postcondition (which can be defined with the Spec class’ IfAfter method) is evaulated after the transition is executed.  If it evaulates to false, the spec will be ignored.  If it evaluates to true, the spec will be verified using the input that was passed into the transition and the output that was returned from the transition.

For this particular spec, we define a postcondition that the spec only needs to be verified if the CacheManager returned one or more null values instead of cached responses.  If the CacheManager returns a null, it means that there was no cached response for the request it was given.  And that is when we need to verify the following things:

  1. The request was handled by the Request Handler
  2. The response that was returned by the Request Handler has been put in the cache
  3. The response array that was returned by the Request Processor contains the expected response

We perform this check for both requests, or only one of them, depending on which one was not in the cache yet.  Remember that the transition will be executed 2000 times using the same request processor and the same cache manager.  Which means that cached responses from previous transition executions might still be in the cache.  Also keep in mind that one of the request types has a defined expiration of 1 second, and the other an expiration of 2 seconds which means that there will be plenty of transition executions where they are either both in the cache, only one of them, or none of them.  All of those cases are now covered with the code in this spec.

Here’s another spec:

        [SpecFor(typeof(ProcessRequestsTransition))]

        public Spec CachedResponsesAreReturnedWhenAvailableInsteadOfCallingTheHandler(Tuple<ProcessInputElement, ProcessInputElement> input, Response[] output)

        {

            return new Spec(() =>

                        {

                            Action<ProcessInputElement> verify =

                                element =>

                                    {

                                        Ensure.False(element.RequestHandlerWasExecuted);

                                        Ensure.True(output.Contains(cacheManager.ReturnedCachedResponses.First(r => r != null && r.GetType() == element.Response.GetType())));

                                    };

 

                            if (cacheManager.ReturnedCachedResponses.Any(r => r != null &&  r.GetType() == input.First.Response.GetType()))

                            {

                                verify(input.First);

                            }

 

                            if (cacheManager.ReturnedCachedResponses.Any(r => r != null && r.GetType() == input.Second.Response.GetType()))

                            {

                                verify(input.Second);

                            }

                        })

                .IfAfter(() => cacheManager.ReturnedCachedResponses.Any(r => r != null));

        }

 

Here we verify that when a cached response was returned by the CacheManager:

  1. The Request Handler was not executed
  2. The response array returned by the Request Processor contains the cached response

We again perform this check for both requests, or only one of them depending on which one had a cached response.

You might think that this was a lot of work, but was it really?  It’s about 160 lines of code, and i’m quite sure that the functionality that i’m testing is covered much more thoroughly than it would’ve been with 160 lines of code for classical unit tests.   In fact, i challenge each one of you to come up with a more thorough test for this in less than 160 lines of code.  Also, i can keep adding specs quite easily and those really don’t contain that much code.  But my functional coverage would increase dramatically, much more than it would with classical unit tests.

Granted, the learning curve is steep as i mentioned already in a previous post.  But once you start to get it, you become pretty productive with it and you’ll catch a lot more bugs before you deliver your software because of it.

Now, i tried hard to make everything here as clear as possible, so i’d love to hear from you whether or not:

  1. you understood it
  2. you like it
  3. you think it’s way over the top
  4. you want to start doing this too

Posted in Test Driven Development, agatha, quicknet | 9 Comments »

How QuickNet Found 2 Bugs That You And I Didn’t

Posted by Davy Brion on 22nd December 2009

I recently posted the first draft of the caching implementation of Agatha.  You might want to take another look at the piece of code that deals with processing requests in the Request Processor.  I thought it was alright.  And if only 10% of my readers actually read that code, then it means that about 200 people thought it was alright too because nobody mentioned a possible problem with that part.  Today i was adding some cached requests/responses to the RequestProcessor’s QuickNet exception handling test.  And lo and behold, 2 bugs showed up that i hadn’t anticipated.

Before i discuss the two bugs, i’d like to explain what the exception handling quicknet test does, and how it works.  It basically calls the request processing code a bunch of times, each time with a set of requests where either none, one or more of the request handlers will throw an exception during the handling of the requests.  The order of the exceptions or which handlers will throw an exception is completely randomized (thanks to QuickNet) and thus it varies from test to test.  This particular QuickNet test will perform 50 testruns, where each testrun consists of 50 transitions that will be executed.  Each transition is a piece of functionality that will be executed (in this case, the processing of requests) with randomized input (in this case, there is a fixed set of requests but which ones will fail will differ with each run of the transition) and after a transition is executed, the relevant specs are verified (in this case, a bunch of checks to make sure that the whole error handling functionality always does what it needs to do) to make sure that the piece of code that you’re testing (your transition, in this case the processing of requests) actually works.

Instead of testing with a mocked caching layer, i used the real thing in the tests.  I also added 2 cached request types to the test request types, and gave one of them an expiration of 1 second, the other an expiration of 2 seconds.  This means that during the entire QuickNet testrun, some requests will return cached responses, some won’t, some cached responses will expire and subsequent requests of that particular type need to be executed and have their responses cached again until they expire.   In the meantime, QuickNet is constantly firing requests at the RequestProcessor, and some of them will randomly fail.  Our specs need to verify that the returned responses always contain the correct exception information for the batch of requests that was processed.

And here’s the beauty of the whole thing.  I hadn’t even thought about how exception handling also influences how you deal with cached responses.  I didn’t take exception handling into account when adding the caching code, and without even adding specific tests to see whether the caching worked correctly, my QuickNet specs that intended to cover something that doesn’t really have anything to do with caching uncovered 2 issues with my caching code.   I was suddenly getting error messages from QuickNet that in some cases, the exception information wasn’t correct.   And it frequently took over 30 executions of the transition, or sometimes multiple testruns before some of those specs would fail.  The longer it takes for a bug to show up in a QuickNet test, the better the bug is at hiding and the harder it is to find it manually because it almost certainly is an edge-case that you hadn’t considered at all and that only occurs in certain situations.

And those are the type of bugs that you typically don’t find with traditional unit tests.  When you write traditional tests that are aimed at asserting correct behavior, you typically only write tests for the problems that you thought about.  Sometimes you’ll get lucky and traditional unit tests will inform you of incorrect behavior that you didn’t think of,  but it rarely happens for the edge-cases.  And those are the bugs that can be really hard and painful to find and fix.

By now you’re probably wondering what the two bugs are.  The first one is that if an exception occurs during the handling of a request which is eligible for caching, the response with the exception information would be stored in the cache, and the next time that that particular request would be processed while the cached response hadn’t expired yet, you’d simply get the original response with the exception information again instead of actually handling the request again (which might have been handled successfully this time).  The second bug was that if an earlier request in the batch of requests already failed, it could possibly return a valid response later on in the same batch for one of the cached requests if its response hadn’t expired yet.   Pretty stupid huh?  But they were there nevertheless, and sooner or later somebody would’ve tripped over it and it would’ve caused frustration for the user who would run into it, and pain for me because i’d have to go looking for it long after i’d written the code.

Again, i seriously doubt that traditional unit tests would’ve prevented the existence of these 2 problems since it never occurred to me while i was writing it.  The QuickNet tests did find it, even before i added specific tests for the caching functionality to them, which i found pretty impressive and a huge benefit to this sort of testing.  Granted, the learning curve for writing valuable QuickNet tests is steep (i’m not even halfway there IMO) and it takes a lot of effort when you’re starting out with it.  But if it helps me prevent the sort of bugs that are otherwise easily missed and could negatively influence the perception of my project, then i definitely consider it worth it.

Posted in Test Driven Development, agatha, quicknet | 4 Comments »

Open Source Licensing, Copyright Notices, Contributions: What To Do?

Posted by Davy Brion on 20th December 2009

There are two interesting problems that i’m facing with open-sourcing Agatha, and i’m not quite sure how to deal with it correctly.  The first is how to apply the license of my choice to the actual code.  I’m using Apache License 2.0, and this is their recommendation (emphasis mine):

To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don’t include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.

 

Copyright [yyyy] [name of copyright owner]

 

Licensed under the Apache License, Version 2.0 (the "License");

you may not use this file except in compliance with the License.

You may obtain a copy of the License at

 

http://www.apache.org/licenses/LICENSE-2.0

 

Unless required by applicable law or agreed to in writing, software

distributed under the License is distributed on an "AS IS" BASIS,

WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and

limitations under the License.

This sort of implies that i’m required to put this boilerplate notice in each file, which is just tedious and the odds are pretty high that you’re going to forget to put this in one (or more) of the files that will be added later on.

Instead, i put a LICENSE.txt file in the root folder of the project with the following content:

Copyright 2009 Agatha RRSL Project, original authors and contributors

 

Licensed under the Apache License, Version 2.0 (the "License");
you may not use the files in this directory structure except in compliance with the License.
You may obtain a copy of the License at

 

http://www.apache.org/licenses/LICENSE-2.0

 

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Honestly, i have no idea if i’m allowed to do that.  I can’t think of a reason why i shouldn’t be able to do this since it certainly sounds reasonable to do so, but then again i’m not a lawyer and i wouldn’t be surprised if there are reasons for not doing so.  If anyone can provide advice on this, it would be much appreciated :)

Another thing that left me wondering is the actual copyright notice.  In the 1.0 release, i unfortunately used the following copyright statement for both the LICENSE.txt as well as the copyright information on the assembly level:

Copyright 2009 Davy Brion

Now, i did write most of the code, i did start the project and i do own the project.  But i did not write all of the code as there have been some contributions from other people.  I certainly want to give credit where credit is due, so i’ve changed that copyright notice (both in the LICENSE.txt file and the assembly copyright notices) to:

Copyright 2009 Agatha RRSL Project, original authors and contributors

I then added a CONTRIBUTORS.txt file at the same location of the LICENSE.txt file which contains the names of the contributors and the parts they worked on.  I think that’s all i need to do to to be fair and correct, but again, i’m not entirely sure on this.

If anyone can provide feedback on these issues, please do so :)

Posted in agatha | 7 Comments »

Agatha 1.0

Posted by Davy Brion on 19th December 2009

I just released Agatha 1.0 which you can download here.  The biggest changes since the 1.0 beta 2 release is the support for the one-way requests and the ability to easily run the service layer within the same process as your client (if you don’t need or want WCF for example).

As for the next version (1.1) the biggest focus will be on the caching layer, and the ability to pick your own error handling strategy.

I hope the few users that we have will enjoy this :)

Posted in agatha | 3 Comments »

Enabling Logging In Your Agatha Service Layer

Posted by Davy Brion on 19th December 2009

As of Agatha 1.0 beta 2, you can now use whatever logging library you prefer.  Agatha now uses the Common.Logging project instead of using a logging library directly.  This means you just need to add a bit of configuration to your service host to enable logging and get that logging information in whatever format or manner you want.  Enabling this is pretty easy, since you just need to follow the standard approaches for configuring Common.Logging, and obviously also for the logging library that you use.  I’m just going to show a short example of using XML in your web.config (or app.config depending on your service host) to get this working.

First, you need to add the configuration section for Common.Logging to the <configSections> element:

    <sectionGroup name="common">

      <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />

    </sectionGroup>

    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>

 

As you can see, i also included the definition of my preferred logging library (log4net) in this as well.  In this particular case, your service host needs to reference the following assemblies: Common.Logging.dll, Common.Logging.Log4Net.dll and log4net.dll.

The configuration of the Common.Logging library looks like this:

  <common>

    <logging>

      <factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4net">

        <arg key="configType" value="INLINE" />

      </factoryAdapter>

    </logging>

  </common>

 

You need to specify which factoryAdapter that Common.Logging will use, in our case the one for log4net.  If you then configure the INLINE value for the configType key, Common.Logging will just initialize log4net in a way that it will simply use the XML configuration that is also present in your config file.  Again, i’ll point you to the Common.Logging documentation for configuring it for your specific library if you’re using something else. 

In my case, my log4net configuration looks like this:

  <log4net>

    <logger name="Agatha">

      <level value="ERROR"/>

      <appender-ref ref="LogFileAppender" />

    </logger>

 

    <logger name="AgathaPerformance">

      <level value="WARNING"/>

      <appender-ref ref="LogFileAppender" />

    </logger>

 

    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender" >

      <param name="File" value="log.txt" />

      <param name="AppendToFile" value="true" />

      <rollingStyle value="Size" />

      <maxSizeRollBackups value="10" />

      <maximumFileSize value="10MB" />

      <staticLogFileName value="true" />

 

      <layout type="log4net.Layout.PatternLayout">

        <param name="ConversionPattern" value="%-5p%d{yyyy-MM-dd hh:mm:ss} – %m%n" />

      </layout>

    </appender>

  </log4net>

 

The ‘Agatha’ logger simply logs everything coming from types whose namespace starts with Agatha and that logs at the error level (basically just exceptions caught by the Request Processor) and sends that the LogFileAppender (which simply logs in a log.txt) file.  The ‘AgathaPerformance’ logger specifically logs performance warnings coming from Agatha’s PerformanceLoggingRequestProcessor and also sends it to the LogFileAppender.

And that’s all there is to it.

Posted in agatha | No Comments »

Agatha’s Caching Layer Implementation: First Draft

Posted by Davy Brion on 13th December 2009

Well i got a bit carried away and started implementing the caching layer already… i’d like to go over the details of it in this post, but keep in mind that it’s only a first draft and that this will not be in the upcoming 1.0 release.   In fact, i haven’t even tested this yet… i don’t even know if it runs.  This is just to get some feedback on the design.  Once it works, it’ll need some time to mature and to be tested properly so it’ll be in the 1.1 release.  With that out of the way, let’s get started.

First of all, there’s the following attribute that you can put on your Request types:

    [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]

    public class EnableResponseCachingAttribute : Attribute

    {

        public string Region { get; set; }

        public int Hours { get; set; }

        public int Minutes { get; set; }

        public int Seconds { get; set; }

 

        public TimeSpan Expiration

        {

            get

            {

                if (Hours == 0 && Minutes == 0 && Seconds == 0)

                {

                    throw new InvalidOperationException("You need to specific at least an hour value, a minute value or a second value");

                }

 

                return new TimeSpan(0, Hours, Minutes, Seconds);

            }

        }

    }

 

I really want to support both programmatic configuration as well as XML configuration (which would always override any existing programmatic configuration for a particular request) but for now, this attribute is the only way.  Also, everything in this caching layer assumes that your requests which enable response caching must override the Equals and GetHashCode() methods correctly (hint: use Resharper for that).

When we configure Agatha, we need to transform the caching metadata into objects of the following class:

    public class RequestCacheConfiguration

    {

        public Type RequestType { get; private set; }

        public TimeSpan Expiration { get; private set; }

        public string Region { get; private set; }

 

        public RequestCacheConfiguration(Type requestType, TimeSpan expiration, string region)

        {

            RequestType = requestType;

            Expiration = expiration;

            Region = region;

        }

    }

 

And we also need something that contains all of the caching configuration data:

    public class CacheConfiguration

    {

        private Dictionary<Type, RequestCacheConfiguration> requestCacheConfigurations;

 

        public CacheConfiguration(IEnumerable<Request> knownRequests)

        {

            BuildMapOfConfigurationsForRequestsThatEnabledResponseCaching(knownRequests);

        }

 

        private void BuildMapOfConfigurationsForRequestsThatEnabledResponseCaching(IEnumerable<Request> knownRequests)

        {

            requestCacheConfigurations = new Dictionary<Type, RequestCacheConfiguration>();

 

            foreach (var request in knownRequests)

            {

                var requestType = request.GetType();

                var attribute = Attribute.GetCustomAttribute(requestType, typeof(EnableResponseCachingAttribute)) as EnableResponseCachingAttribute;

 

                if (attribute != null)

                {

                    requestCacheConfigurations.Add(requestType, new RequestCacheConfiguration(requestType, attribute.Expiration, attribute.Region));

                }

            }

        }

 

        public bool IsCachingEnabledFor(Type requestType)

        {

            return requestCacheConfigurations.ContainsKey(requestType);

        }

 

        public RequestCacheConfiguration GetConfigurationFor(Type requestType)

        {

            return requestCacheConfigurations[requestType];

        }

 

        public IEnumerable<string> GetRegionNames()

        {

            return new HashSet<string>(requestCacheConfigurations.Values.Where(v => !string.IsNullOrEmpty(v.Region)).Select(v => v.Region));

        }

 

        public string GetRegionNameFor(Type requestType)

        {

            return requestCacheConfigurations[requestType].Region;

        }

    }

 

These classes already give us all we need to know (for now, at least) to set up our cache.  As mentioned previously, i wanted to use a region-based approach like NHibernate’s 2nd Level Cache.  Each region is basically a logical cache (and depending on the caching provider you’ll use, perhaps even a separate physical one) which is separated from the other ones.  It gives us the ability to specifically clear a logical cache.

So, we need something which can create a cache for a region:

    public interface ICacheProvider

    {

        ICache BuildCache(string region);

    }

 

And the cache itself would need to expose the following methods:

    public interface ICache

    {

        Response GetCachedResponseFor(Request request);

        void Store(Request request, Response response, TimeSpan expiration);

        void Clear();

    }

 

So now we can write something that manages the whole caching thing.  I couldn’t come up with a good name, so i just named the class CacheManager (i know it sucks, so suggest a better name if you know one):

    public interface ICacheManager

    {

        bool IsCachingEnabledFor(Type requestType);

        Response GetCachedResponseFor(Request request);

        void StoreInCache(Request request, Response response);

        void Clear(string region);

    }

 

    public class CacheManager : ICacheManager

    {

        private const string defaultRegion = "_defaultRegion";

 

        private readonly CacheConfiguration configuration;

        private readonly ICacheProvider cacheProvider;

        private Dictionary<string, ICache> caches;

 

        public CacheManager(CacheConfiguration configuration, ICacheProvider cacheProvider)

        {

            this.configuration = configuration;

            this.cacheProvider = cacheProvider;

            BuildCaches();

        }

 

        private void BuildCaches()

        {

            var regions = configuration.GetRegionNames();

            caches = new Dictionary<string, ICache>(regions.Count() + 1);

            caches.Add(defaultRegion, cacheProvider.BuildCache(defaultRegion));

 

            foreach (var region in regions)

            {

                caches.Add(region, cacheProvider.BuildCache(region));

            }

        }

 

        public bool IsCachingEnabledFor(Type requestType)

        {

            return configuration.IsCachingEnabledFor(requestType);

        }

 

        public Response GetCachedResponseFor(Request request)

        {

            return caches[configuration.GetRegionNameFor(request.GetType()) ?? defaultRegion].GetCachedResponseFor(request);

        }

 

        public void StoreInCache(Request request, Response response)

        {

            var config = configuration.GetConfigurationFor(request.GetType());

            caches[config.Region ?? defaultRegion].Store(request, response, config.Expiration);

        }

 

        public void Clear(string region)

        {

            caches[region].Clear();

        }

    }

 

The RequestProcessor’s ugly request-processing-loop (i know i need to clean that up) could then look like this:

            foreach (var request in requests)

            {

                try

                {

                    var cachingIsEnabledForThisRequest = cacheManager.IsCachingEnabledFor(request.GetType());

 

                    if (cachingIsEnabledForThisRequest)

                    {

                        var cachedResponse = cacheManager.GetCachedResponseFor(request);

 

                        if (cachedResponse != null)

                        {

                            responses.Add(cachedResponse);

                            continue;

                        }

                    }

 

                    using (var handler = (IRequestHandler)IoC.Container.Resolve(GetResponseHandlerTypeFor(request)))

                    {

                        try

                        {

                            if (!exceptionsPreviouslyOccurred)

                            {

                                var response = GetResponseFromHandler(request, handler);

                                exceptionsPreviouslyOccurred = response.ExceptionType != ExceptionType.None;

                                responses.Add(response);

 

                                if (cachingIsEnabledForThisRequest)

                                {

                                    cacheManager.StoreInCache(request, response);

                                }

                            }

                            else

                            {

                                var response = handler.CreateDefaultResponse();

                                response.ExceptionType = ExceptionType.EarlierRequestAlreadyFailed;

                                response.Exception = new ExceptionInfo(new Exception(ExceptionType.EarlierRequestAlreadyFailed.ToString()));

                                responses.Add(response);

                            }

                        }

                        finally

                        {

                            IoC.Container.Release(handler);

                        }

                    }

                }

                catch (Exception e)

                {

                    logger.Error(e);

                    throw;

                }

            }

 

And that’s it, so far.   Obviously, we need ICache and ICacheProvider implementations for the various caching libraries that are already available.  I already wrote an InMemoryCache and InMemoryCacheProvider to facilitate early experimentation/testing of the caching layer:

    public class InMemoryCacheProvider : ICacheProvider

    {

        public ICache BuildCache(string s)

        {

            return new InMemoryCache();   

        }

    }

 

    // this class should probably never be used in production, but will be useful for testing ;)

    public class InMemoryCache : ICache

    {

        private readonly object monitor = new object();

        private Dictionary<Request, Response> cachedResponses;

        private Dictionary<Timer, Request> timersToRequests;

 

        public InMemoryCache()

        {

            Initialize();

        }

 

        private void Initialize()

        {

            cachedResponses = new Dictionary<Request, Response>();

            timersToRequests = new Dictionary<Timer, Request>();

        }

 

        public Response GetCachedResponseFor(Request request)

        {

            lock(monitor)

            {

                if (!cachedResponses.ContainsKey(request))

                {

                    return null;

                }

 

                return cachedResponses[request];

            }

        }

 

        public void Store(Request request, Response response, TimeSpan expiration)

        {

            var timer = new Timer(expiration.Milliseconds);

 

            lock (monitor)

            {

                if (cachedResponses.ContainsKey(request))

                {

                    // another request handler stored a cached response already during the processing of this request…

                    // the last one wins, so get rid of the previous one, including its timer

                    cachedResponses.Remove(request);

                    var otherTimer = timersToRequests.First(keyValuePair => keyValuePair.Value.Equals(request)).Key;

                    GetRidOfTimer(otherTimer);

                    timersToRequests.Remove(otherTimer);

                }

 

                cachedResponses[request] = response;

                timersToRequests[timer] = request;

            }

 

            timer.Elapsed += timer_Elapsed;

            timer.Start();

        }

 

        void timer_Elapsed(object sender, ElapsedEventArgs e)

        {

            var timer = (Timer)sender;

 

            lock (monitor)

            {

                // if the Clear method has been called before a timer has elapsed, it won’t be in the timersToRequest dictionary anymore

                if (timersToRequests.ContainsKey(timer))

                {

                    var request = timersToRequests[timer];

                    cachedResponses.Remove(request);

                    timersToRequests.Remove(timer);

                }

            }

 

            timer.Dispose();

        }

 

        public void Clear()

        {

            lock(monitor)

            {

                foreach (var timer in timersToRequests.Keys)

                {

                    GetRidOfTimer(timer);

                }

 

                Initialize();

            }

        }

 

        private void GetRidOfTimer(Timer timer)

        {

            timer.Elapsed -= timer_Elapsed;

            timer.Stop();

            timer.Dispose();

        }

    }

 

That’s it so far… i probably forgot about a lot of stuff that i really should take into account, but at least it’s something that we can start with.  Or to throw away and start over :)

Posted in agatha | 8 Comments »

Agatha Feature Suggestion: Caching

Posted by Davy Brion on 12th December 2009

Someone recently asked me if it would be possible to cache responses with an Agatha service layer and just send back the cached responses when matching requests are sent to the service layer.  I’ve been thinking about this a bit lately, and i think it would be a tremendous feature.  In this post, i just want to list a couple of ideas on how it could work and what we’d need to take into account to make it work.  Please feel free to leave your suggestions/thoughts on this since i can definitely use all of the feedback i can get to implement a feature like this.

The idea is basically to implement a caching layer which works very similar to NHibernate’s Second Level Cache.  You would need to be able to define which request/response combination is eligible for caching.  When a request/response combination is eligible for caching, Agatha should check to see if a cached response is already available for a particular incoming request.  That would mean that the request type would need to override the Equals method to compare the values.   If a previous request has already been processed which is equal to the current request, the corresponding cached response could be sent back immediately without having to handle it again.  Obviously, this check would only happen for requests which have been made eligible for caching.

We’d also need to provide a way to invalidate the cache.  Both time-based expiration and explicit removal from the cache should be possible.  For time-based expiration we could just provide some sort of time-out setting in the same place where you enable the caching for the request.  I’d probably do that through a .NET attribute which you can put on your Request type, and the time-out would simply be a property of the attribute.  For explicit removal, i’d probably go with a ‘region’-approach, similar to the regions in NHibernate’s Second Level Cache.  For instance, when declaring a request to be eligible for caching, one of the properties of the caching attribute could be a region name, and then we’d need to give you the ability to clear a certain region of the cache in your request handlers when it’s necessary to do so.

That’s pretty much all i can think of for now.  It’s not much yet, but i do think it could really be a tremendous improvement to Agatha.  The performance benefits for requests that deal with mostly static data, or data that doesn’t change frequently could be huge.  And the required coding effort for developers using Agatha would be minimal… simply put the correct attribute on your request type and explicit clearing of the right cache region when necessary would be all there is to it.

Thoughts?

Posted in agatha | 7 Comments »

Agatha’s First (Vocal) Happy User

Posted by Davy Brion on 9th December 2009

This made my day.

Favorite quote from the post:

When I read about this it looked good. After one day of using it, I’m impressed, … really impressed.
It doesn’t use a lot of fancy patterns, just some tried and tested basic OO stuff, and it forces you to abide by these rules.

Posted in agatha | No Comments »