Skip to content

Brighter MySQL Command Store

I’ve been wanting to explore Brighter for awhile, probably over a year.  I figured I’d try something new this time around and actually explore it by contributing to the project itself.  I noticed there were no Command and Message Stores yet supporting MySQL.  Turns out it was pretty straight forward to port the Sqlite Message & Command over to MySQL.  So that’s what I did, created a Brighter MySQL Command Store.

Brighter

First, if you’re unfamiliar with Brighter, here’s a quick description:

This project is a Command Processor & Dispatcher implementation that can be used as a lightweight library in other projects.

It can be used for implementing Ports and Adapters and CQRS (PDF) architectural styles in .NET.

In addition, Brighter supports Distributed Task Queues. As such it can be used to improve performance by introducing concurrency using a queue, and/or as an integration strategy between Microservices using messaging via a lightweight broker.

I like to think of Brighter as your possible next step from MediatR.  Since everything in MediatR is in process, which is great in many situations, it can also be less ideal in others.  When you need task queues, retry,  and circuit breaker type functionality is where Brighter can help right out of the box.

Command Sourcing

Don’t confuse Command Sourcing with Event Sourcing.  If you are, check out the Brighter docs that go into it a bit to clarify.

Any command dispatched with Brighter can be stored.  It’s actually pretty straightforward to setup.  I’m going to use the new MySqlCommandStore that I recently created as the example.

Register IAmCommandStore

First thing you need to do is register the MySqlCommandStore as a IAmACommandStore and/or IAmACommandStoreAsync, in the container you are using in your HandlerConfiguration.  Here’s a modified version of the HelloWorld sample.

For reference, the two parameters in the MySqlCommandStoreConfiguration are the connection string and the table name.

internal class Program
{
private static void Main(string[] args)
{
var registry = new SubscriberRegistry();
registry.Register<GreetingCommand, GreetingCommandHandler>();
var tinyIoCContainer = new TinyIoCContainer();
tinyIoCContainer.Register<IHandleRequests<GreetingCommand>, GreetingCommandHandler>();
var commandStore =
new MySqlCommandStore(
new MySqlCommandStoreConfiguration("Server=localhost;Uid=root;Pwd=root;Database=BrighterTests",
"commands"));
tinyIoCContainer.Register<IAmACommandStore>(commandStore);
tinyIoCContainer.Register<IAmACommandStoreAsync>(commandStore);
var builder = CommandProcessorBuilder.With()
.Handlers(new HandlerConfiguration(
subscriberRegistry: registry,
handlerFactory: new TinyIocHandlerFactory(tinyIoCContainer)
))
.DefaultPolicy()
.NoTaskQueues()
.RequestContextFactory(new InMemoryRequestContextFactory());
var commandProcessor = builder.Build();
var greetingCommand = new GreetingCommand("Derek");
commandProcessor.Send(greetingCommand);
var retrievedCommand = commandStore.Get<GreetingCommand>(greetingCommand.Id);
Console.WriteLine(string.Format("Command retrieved from store: {0}", JsonConvert.SerializeObject(retrievedCommand)));
Console.ReadLine();
}
}
view raw program.cs hosted with ❤ by GitHub

UseCommandSourcing Attribute

Second and last step is to add the UseCommandSourcing attribute to the command handler you want to persist into command store (MySQL table).

internal class GreetingCommandHandler : RequestHandler<GreetingCommand>
{
[UseCommandSourcing(step: 1, timing: HandlerTiming.Before)]
public override GreetingCommand Handle(GreetingCommand command)
{
Console.WriteLine("Hello {0}", command.Name);
return base.Handle(command);
}
}

Result

When I run the sample app, here is the console output:

And the resulting record now stored in our MySQL database:

More

I plan on blogging more about Brighter in the near future.  Are you using Brighter?  Are there any specific features or topics you would like me to cover?  Let me know in the comments or on Twitter.

Leave a Reply

Your email address will not be published. Required fields are marked *