One-Way (Or Fire And Forget) Requests With Agatha
Posted by Davy Brion on December 4th, 2009
Arjen Smits recently submitted a patch for Agatha which makes it possible to send One-Way (aka Fire And Forget) requests to an Agatha service layer. As you know, Agatha is a Request/Response framework where each Request sent to the service layer will receive a corresponding Response. A One-Way request doesn’t have a response however. It can be very useful when you just need the service layer to do something where the client that sent the request doesn’t need a response, and thus, shouldn’t have to wait for it.
The biggest benefit here is that client can simply send a One-Way request to the service layer, and instead of waiting for the service layer to process it, the call to the service layer will return immediately. You could achieve similar behavior by using the asynchronous service proxy and supplying an empty delegate to be called after the response was received. The downside of that is obviously that the communication channel between the client and the server would remain in use throughout the handling of the request, only to return a response later on that will be ignored anyway. Sending a One-Way request avoids this kind of waste.
Let’s see how we can use One-Way requests with Agatha.
First of all, you will need to create a Request class which inherits from Agatha’s OneWayRequest class:
public abstract class OneWayRequest : Request
{
}
Normally you’d also create a corresponding Response type for your Request type, but for Requests that inherit from OneWayRequest that’s useless. You’ll also need to create a Request Handler which inherits from Agatha’s OneWayRequestHandler class:
public abstract class OneWayRequestHandler<TRequest> : OneWayRequestHandler, IOneWayRequestHandler<TRequest> where TRequest : OneWayRequest
{
public override void Handle(OneWayRequest request)
{
var typedRequest = (TRequest) request;
BeforeHandle(typedRequest);
Handle(typedRequest);
AfterHandle(typedRequest);
}
public virtual void BeforeHandle(TRequest request) { }
public virtual void AfterHandle(TRequest request) { }
public abstract void Handle(TRequest request);
}
This is very similar to a regular RequestHandler, except that there’s no way for you to return a response. Simply inherit from this class, implement the Handle(TRequest) method to perform whatever it is that you need to do and that’s it as far as the service layer is concerned. If you want to, you can (as always) override the BeforeHandle and AfterHandle methods to add some extra stuff. If you don’t want to inherit from this OneWayRequestHandler class, you can just as well create a class which implements Agatha’s IOneWayRequestHandler<TRequest> interface. Your One Way Request Handlers will be picked up and registered by Agatha automatically, just as it does with regular Request Handlers.
As for sending One Way Requests to your service layer, you can do that with both the synchronous IRequestDispatcher and the IAsyncRequestDispatcher. The IRequestDispatcher interface now looks like this:
public interface IRequestDispatcher : IDisposable
{
IEnumerable<Response> Responses { get; }
void Add(Request request);
void Add(params Request[] requestsToAdd);
void Add(string key, Request request);
void Send(params OneWayRequest[] oneWayRequests);
bool HasResponse<TResponse>() where TResponse : Response;
TResponse Get<TResponse>() where TResponse : Response;
TResponse Get<TResponse>(string key) where TResponse : Response;
TResponse Get<TResponse>(Request request) where TResponse : Response;
void Clear();
}
Sending OneWayRequests can be done through the Send method, which will immediately send the given OneWayRequests to the service layer and the call will return as soon as the requests have been transmitted. This means that this call will block for a short time until the requests have actually been sent. It will return before the requests are actually processed by the service layer however.
The IAsyncRequestDispatcher now looks like this:
public interface IAsyncRequestDispatcher : IDisposable
{
void Add(Request request);
void Add(params Request[] requestsToAdd);
void Add(string key, Request request);
void Add(params OneWayRequest[] oneWayRequests);
void ProcessOneWayRequests();
void ProcessRequests(Action<ReceivedResponses> receivedResponsesDelegate, Action<ExceptionInfo> exceptionOccurredDelegate);
void ProcessRequests(Action<ReceivedResponses> receivedResponsesDelegate, Action<ExceptionInfo, ExceptionType> exceptionAndTypeOccurredDelegate);
}
You can add your OneWayRequest through the correct Add method, and then have them processed by the server by calling the ProcessOneWayRequests method. This call will not block and will return immediately. That means that it won’t wait until the requests have actually been sent to the server like it does with the IRequestDispatcher.

December 4th, 2009 at 9:16 pm
Hi, I am working on an ASP.NET MVC project and I’m very interested in using a Request/Response architecture to help simplify the project. We don’t need WCF/Silverlight (not yet, at least). Furthermore, to facilitate database transaction rollbacks and more generally just to keep things simple, we would like to maintain synchronized program flow. Is Agatha overkill for our needs? Does Agatha require WCF to operate correctly? Any suggestions for using Agatha in an MVC project?
Thanks,
Brad
December 5th, 2009 at 11:17 am
Agatha doesn’t require WCF, though you would have to configure it slightly differently than usual and the OneWayRequest stuff wouldn’t truly be one-way either (unless you use the async proxy)
Other than that, it should work just fine… i suggest you just give it a shot in a spike and see for yourself whether you like it or not
December 11th, 2009 at 7:00 pm
I really like Agata as is, but is it possible to use it with MSMQ (async model for Send and sync model for Receive)?
December 12th, 2009 at 1:33 pm
it’s not possible yet, but i think it could be done. We’d need a MSMQ-specific implementation of IAsyncRequestProcessor which adds the one-way requests to the queue and you’d need a server-side component which reads the messages (the one-way requests) off of the queue and pushes them to the Request Processor.
December 14th, 2009 at 11:08 am
What happens if there are problems with sending or handling the request?
I suppose the client will not notice at all, in which case it should only be used for requests that can be lost. This has to be carefully evaluated to avoid breaking the application.
December 14th, 2009 at 11:13 am
@Adam
if there is a problem with handling the request, it will be logged by Agatha in the server-side log
if there is a problem with sending a synchronous one-way request, you will get an exception (since it blocks until the request is _sent_ but once it’s sent, the call returns)
if there is a problem with sending an asynchronous one-way request, then you’ll indeed never know about it