Per Brage's Blog

const String ABOUT = "Somehow related to code";

Event Broker using Rx and SignalR (Part 4: Solving the Scenario)

The time has come to start implementing the scenario. The scenario I invented, and then refactored from a science fiction novel into this simple online shop, which just happens to sell computers and components. As promised earlier, by the time you are reading this post the full source will be available on my GitHub repository, just follow the link below.

Configuration

This post will wrap up the series with the fluent configuration for our brokers; Website, ComponentStock, ComputerStock and Procurement. Let’s begin with the website since that’s where everything starts.

Website

The website creates the event broker by specifying a publishingUri, which will register the event broker so subscribers can connect to it. We can also see how a local subscription is added here, which we will use for sending out confirmation mails within our ProductOrderedEventConsumer. Then we start ordering products and publish the events using the OrderProduct() method, which just randomly creates ProductOrderedEvents.


            using (var eventBroker = new EventBroker("http://localhost:53000/"))
            {
                eventBroker.Locally().Subscribe(new ProductOrderedEventConsumer());

                Console.WriteLine("Press any key to start ordering products");
                Console.ReadKey();

                for (var i = 0; i < 30; i++)
                {
                    eventBroker.Publish(OrderProduct());
                    Thread.Sleep(200);
                }

                Console.ReadKey();
            }

Computer and Component stock

Both our computer and component stock register themselves to allow remote subscribers, while they also remotely subscribe to ProductOrderedEvent (through an event consumer). Internally, but not shown here, the event consumer for the computer stock makes use of a specification to filter the incoming events, whereas the component stock uses lambdas to show the difference.


            using (var eventBroker = new EventBroker("http://localhost:53001/"))
            {
                eventBroker.ConnectionStatus += (s, ev) => 
                    Console.WriteLine("Component stock: " + (ev.Success ? "Connected!" : ev.ErrorMessage));
                eventBroker
                    .Locally()
                        .Subscribe<ProductShippedEvent>(x => 
                            Console.WriteLine(String.Format("{0} order packed and shipped", x.ProductName)))
                    .Remotely("http://localhost:53000/")
                        .Subscribe(new ProductOrderedEventConsumer(eventBroker));

                Console.ReadKey();
            }


    public class ProductOrderedEventConsumer : EventConsumer<ProductOrderedEvent>
    {
        private readonly IEventBroker _eventBroker;
        private readonly Random _random;

        public ProductOrderedEventConsumer(IEventBroker eventBroker)
        {
            _eventBroker = eventBroker;
            _random = new Random();

            RegisterSpecification(new ItemsInLaptopOrComputerProductGroupSpecification());
        }

        public override void Handle(ProductOrderedEvent @event)
        {
            _eventBroker.Publish(new ProductShippedEvent
                                     {
                                         ProductName = @event.ProductName
                                     });

            if (_random.Next(10) > 5)
                _eventBroker.Publish(new ProductOrderPointReachedEvent()
                                         {
                                             ProductName = @event.ProductName
                                         });
        }
    }

Procurement

The last of our configurations! We set up remote subscriptions to our stocks and start listening for events telling us that the order point was reached, so procurement can order new products to fill up our stocks. Here you can also see an example of dual remote subscriptions added through the fluent API.


            using (var eventBroker = new EventBroker())
            {
                eventBroker.ConnectionStatus += (s, ev) => 
                    Console.WriteLine("Procurement: " + (ev.Success ? "Connected!" 
                                                                          : ev.ErrorMessage));
                eventBroker.Remotely("http://localhost:53001/")
                                .Subscribe(new ProductOrderPointReachedEventConsumer())
                            .Remotely("http://localhost:53002/")
                                .Subscribe(new ProductOrderPointReachedEventConsumer());

                Console.ReadKey();
            }

Result

By running the solution you will see four console windows, which will display information when they receive and process an event. I added links to images for each console window as an example of how they would look after completing 30 product orders. But a better example of the result would be to run the source available in my repository.

Website console window
Component stock console window
Computer stock console window
Procurement console window

Links

Source
Full source at my GitHub repository

Navigation
Part 1: A Fluent API
Part 2: Implementation
Part 3: Event Consumers
Part 4: Solving the Scenario

Advertisements

4 responses to “Event Broker using Rx and SignalR (Part 4: Solving the Scenario)

  1. Mike May 23, 2012 at 07:01

    Fantastic post. Thanks!

  2. Bradley Scott June 2, 2012 at 23:35

    Is it equally possible to have a Javascript subscriber to this event broker? It’s not entirely clear to me.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: