MiniBuss is a micro service bus on top of MSMQ and fits within a single source file.
NOTE that MiniBuss is still a work in progress and even though it is being used in production, be careful and test, test, test.
MiniBuss is best downloaded from NuGet, and currently there is only one package - MiniBuss. From the Package Manager Console type:
PM> Install-Package MiniBuss
This will create a new folder in your project called "MiniBuss" with a single file in it called ServiceBus.cs which contains all the source. The package will also add references to 2 additional .NET libraries; System.Messaging and System.Transactions.
If installing the repo source, remember to add references to System.Messaging and System.Transactions.
The best way to get started may be to download the solution from the source code which contains a number of very simple projects for send/receive and publish/subscribe# The samples below are taken from the sample code.
Setting up a sender may look something like this:
var bus = new ServiceBus();
bus.RegisterMessageEndpoint<HelloCommand>("minibuss_receiver1@johan-dell-ssd");
bus.Send(new HelloCommand { Guid = Guid.NewGuid(), Message = "Hello" });
Create the bus, register a message and tell it where messages of this type should go and send the message. Note that you don't have to create a local endpoint or start the bus when just sending a message. The remote endpoint must exist for the bus to be able to send a message though, or there will be an exception. There is no local queue where messages are written to and then sent - messages are delivered directly. Nothing prevents you from creating a store and forwad solution with MiniBuss.
Setting up a receiver may look something like this:
var bus = new ServiceBus { LocalEndpoint = "minibuss_receiver1" };
bus.RegisterMessageHandler<HelloCommand>(command =>
Console.WriteLine(command.Message + " Guid: " + command.Guid));
bus.Start();
Create the bus and tell it which endpoint to listen to (which creates a local MSMQ queue if necessary) and tell it which message type to listen for and which delegate to kick off when such a message is received.
Similarly, when doing a receive/reply, you would have to create the bus on the sender side with a local endpoint and register a message-handler for replies, like this:
var bus = new ServiceBus { LocalEndpoint = "minibuss_sender1" };
bus.RegisterMessageEndpoint<HelloCommand>("minibuss_receiver1@johan-dell-ssd");
bus.RegisterMessageHandler<HelloResponse>(reply =>
Console.WriteLine("Reply from receiver: " + reply.Message));
bus.Start();
Console.WriteLine("Sending command...");
bus.Send(new HelloCommand { Guid = Guid.NewGuid(), Message = "Hello" });
The receiver would do a bus.reply() like this:
var bus = new ServiceBus { LocalEndpoint = "minibuss_receiver1" };
bus.RegisterMessageHandler<HelloCommand>(command =>
{
Console.WriteLine(command.Message + " Guid: " + command.Guid);
bus.Reply(command, new HelloResponse { Guid = Guid.NewGuid(), Message = "Hello back!" });
});
bus.Start();
The MiniBus also supports publish to multiple subscribers. A simple publisher would create a bus with a local endpoint (to receive subscribe/unsubscribe commands), tell it to handle subscriptions for a certain event, then start publishing something every 5 seconds (as an example):
var bus = new ServiceBus { LocalEndpoint = "minibuss_publisher1" };
bus.HandleSubscriptionsFor<SomethingHappenedEvent>();
bus.Start();
Task.Factory.StartNew(() => PublishingThread(bus), TaskCreationOptions.LongRunning);
Console.WriteLine("Done, press ENTER to exit");
Console.ReadLine();
private static void PublishingThread(IServiceBus bus)
{
while (true)
{
Thread.Sleep(5000);
var guid = Guid.NewGuid();
Console.WriteLine("Publishing event with guid " + guid);
bus.Publish(new SomethingHappenedEvent() { Guid = guid, Sent = DateTime.Now });
}
}
Any clients interesting in subscribing to events from the publisher would create a bus with a local endpoint, start the bus and then send a subscribe command to the publisher, telling it you’re interested in subscribing to a certain type of event and which delegate to handle it:
var bus = new ServiceBus {LocalEndpoint = "minibuss_subscriber1"};
bus.Start();
bus.Subscribe<SomethingHappenedEvent>("minibuss_publisher1@localhost", @event =>
{
Console.WriteLine("something happened at {0}, event id {1}",
@event.Sent, @event.Guid);
});
Console.WriteLine("Waiting for events, press ENTER to exit");
Console.ReadLine();
bus.UnSubscribe<SomethingHappenedEvent>("minibuss_publisher1");
If there's an exception in a message handler, the message will be moved to an xxxxxx_error queue created by MiniBuss. There is no retry (yet).
MiniBuss supports use of TransactionScope() if the underlying MSMQ queue is transactional. When the service bus is started, MiniBuss will always create a transactional MSMQ queue if the queue doesn't already exist.
When creating an endpoint, you're always working on your local computer localhost using a syntax like this:
var bus = new ServiceBus { LocalEndpoint = "MyEndpoint" };
This will create a local private queue called your-computer-name\private$\MyEndoint
When telling a message/command to go to an endpoint on the same/local machine:
bus.RegisterMessageEndpoint<HelloCommand>("MyEndpoint");
//or
bus.RegisterMessageEndpoint<HelloCommand>("MyEndpoint@localhost");
or if you want to send a message/command to a remote endpoint:
bus.RegisterMessageEndpoint<HelloCommand>("MyEndpoint@some-other-computer");