Hey ServiceStack,
I was faced with a problem, “What if I want to scan an assembly an register all of the available handlers that are in it?”. I am not sure where this goes or even if it goes here but you can tell me and we can move it accordingly.
For a little background, I came from a recent large application that used EasyNetQ as the library used for interfacing with RabbitMQ. They had a nifty feature that let you scan an assembly and it would register your handlers for you. I just started a new project and decided to use Redis for my MQ solution this time around. When I was going through the API, I noticed there was no functionality to do the same for Redis queues. I created a solution for scanning an assembly, finding all of the implementations of `IRegisterAsHandler and registering the type and accompanying handler. The questions here are:
- Did I over-simplify or over-complicate with my implementation
- Is there anything you would change?
Here is my solution and I will not go into great detail here because it is pretty straight-forward.
-
IRegisterAsHandler
public interface IRegisterAsHandler
{
void Register(RedisMqServer mqServer);
} -
Handles<TMessageType>
public abstract class Handles : IRegisterAsHandler
{
private int _totalMessagesProcessed;
private int _totalMessagesFailed;
private int _totalRetries;
private int _totalNormalMessagesReceived;
private int _totalPriorityMessagesReceived;
private DateTime? _lastMessageProcessed;public Type MessageType => typeof(TMessageType); public Func<IMessage<TMessageType>, object> RegisterFunc() { return message => { try { UpdateStats(message); Handle(message); } catch (Exception) { _totalMessagesFailed++; } return null; }; } public abstract void Handle(IMessage<TMessageType> message); public virtual IMessageHandlerStats GetStats() { return new MessageHandlerStats(GetType().Name, _totalMessagesProcessed, _totalMessagesFailed, _totalRetries, _totalNormalMessagesReceived, _totalPriorityMessagesReceived, _lastMessageProcessed); } private void UpdateStats(IMessage<TMessageType> message) { _totalMessagesProcessed++; if (message.RetryAttempts > 0) _totalRetries++; if (message.Priority == 0) _totalNormalMessagesReceived++; else if (message.Priority > 0) _totalPriorityMessagesReceived++; _lastMessageProcessed = DateTime.UtcNow; } public void Register(RedisMqServer mqServer) { mqServer.RegisterHandler(RegisterFunc()); }
}
-
HelloHandler
- Example of the end productpublic class HelloHandler : Handles
{
public override void Handle(IMessage message)
{
Log.Info(message.Dump());
}
} -
Tie is all together in the MQ Server Initialization
mqServer.RegisterHandlers(typeof(Handles<>).Assembly);
That’s it. The other question is, if this is a valuable piece of code to the community, how do I know? Where do we, as ServiceStack developers, go to see who needs what? I appreciate your time and hopefully you can give me some good constructive criticism on how we can make this better (i.e: maybe add some interfaces to make it available for other MQ Server types, etc.)
Thanks,
Ryan