mdevilliers / SignalR.RabbitMq

MessageBus implementation using RabbitMq as the backing store.
MIT License
89 stars 40 forks source link

Example #2

Closed quintonv closed 11 years ago

quintonv commented 11 years ago

Hi

Is it possible to add a extra example? A windows or console app that publishes to the same topic on rabbit? I tried implementing rabbit into a publisher but it just crashes the mvc web app.

Thanks Q

mdevilliers commented 11 years ago

Hey Quintonv,

The key to publishing to the same topic is ensuring the format of the message on the queue is the same as Signalr is providing.

Add a log queue to the SignalR exchange, trap the messages and you'll see the format. The format is Json and pretty straight forward.

The format however is subject to change and with SignalR moving to a 1.0 it has changed completely.

I am currently working on reworking the project for SignalR 1.0 and might add the example you are after but not until I have spoken to David Fowler to assertain if this part of the SignalR api is more fixed.

Thanks,

Mark

.

mdevilliers commented 11 years ago

Sorry didn't mean to close the issue - will keep it open as an enhancement.

quintonv commented 11 years ago

Thanks for the feedback, will try the log approach to get the formatting.

Hopefully the format remains stable after the 1.0 changes

danbarua commented 11 years ago

This interesting... it looks like you can short-circuit SignalR by pumping messages into RabbitMQ from another process and SignalR will broadcast them to all connected clients. That's ridiculously useful... I wonder if there are any side-effects?

edit yes this is a really stupid idea.

mdevilliers commented 11 years ago

Hey Dan - how are things? ,

I'm not too sure it is a silly idea - the use case would be that you would want another process to take part in a "push" enabled application. Maybe the process would have functionality that you wouldn't want running in your stateless web application.

You know where I work so maybe an example application might be one that integrated with a telephony system making phone calls but that also wished to send notifications to a web page.

Of course there is another way to do this - you can have the process connect via the SignalR.Client api.

I have coded up both ways and can see worth in the two different processes.

If you look at the dev branch you will see I've updated the library for preparation of the 1.0 release of SignalR. There is a working example of this - it would be great if you could find time to have a look at it?

mdevilliers commented 11 years ago

Hey quintonv,

As I've mentioned to Dan - if you check out the Dev branch I've added an example of listening in to messages from another process e.g. a console application.

If you set the start up projects to both the SignalR.RabbitMQ.Console and the SignalR.RabbitMq.Example projects then start sending messages with the web app you should see them displayed in the console box.

var connectionfactory = new ConnectionFactory
        {
            UserName = "guest",
            Password = "guest"
        };

var rabbitMqExchangeName = "SignalRExchange";

_rabbitConnection = new RabbitConnection(connectionfactory, rabbitMqExchangeName);

var eavesdropper = new RabbitConnectionEavesdropper(_rabbitConnection);

//these are message sent to and from the Chat Hub in the web project.
eavesdropper.ListenInOnClientMessages("userJoined", invocation => { System.Console.WriteLine("User joined with connectionid : {0}", invocation.Args[0]); });

_rabbitConnection.StartListening();

This will listen for messages where you want to call the "userJoined" method on the client. In this case the console application is another client.

There is also an example of sending a message to the rabbitmq queue that will only be delivered to a specific client. The example is using an alpha build of SignalR 1.0 and the internal format did change!

Anyway it would be great if you had time to have a look at it?

danbarua commented 11 years ago

Hi Mark, I've already pulled it and played with it. I've been working on something similar - a RabbitMQ MessageQueueHost implementation for ServiceStack (as an alternative to Redis)... I'll catch you on Skype and share some ideas.

As for injecting messages, our use cases are the same - telephony paired with the real-time web. I was envisaging a background thread pulling messages off RabbitMQ and invoking methods on Hubs or maybe even making HTTP requests (yuck) but if there was a way to short-circuit that it would be sweet.

I experimented and it worked with the IMessageBus implementation on master... I could pretend to be a SignalR connection and inject a message and it would be broadcast to all clients. (Here be dragons - one incorrectly formatted message will completely bork SignalR)... then I tried it with the ScaleOutMessageBus implementation on dev (manually editing the JSON) and SignalR was not happy.. the ClientHubInvokation approach looks nice and clean though, I didn't know you could do that.

danbarua commented 11 years ago

ok, according to dfowler the proper way to do it is calling the Hub API.

mdevilliers commented 11 years ago

Hey Dan, If you have time can you have a look now I've updated incorporating dfowler's comments.


var factory = new ConnectionFactory
{
    UserName = "guest",
    Password = "guest"
};

var exchangeName = "SignalRExchange";
GlobalHost.DependencyResolver.UseRabbitMq(factory, exchangeName);

var hubContext = GlobalHost.ConnectionManager.GetHubContext<Chat>();

Task.Factory.StartNew(
    () =>
        {
            while (true)
            {
                hubContext.Clients.All.onConsoleMessage("Hello!");
                Thread.Sleep(1000);
            }
        }
    );

Sending messages over the message bus via rabbitmq but fully supported. The best thing about this is that you can do a full broadcast e.g. hubContext.Clients as well as hubContext.Clients[someconnectionIdentifier].

It would be good to get some feedback.

danbarua commented 11 years ago

Hi Mark, looks cool, will have a play with it when I get the chance.

Can we broadcast to specific Groups this way? That's useful in multi-tenanted systems like ours.

"It might be interesting to send messages directly to connected clients from another process."

Wait... what is this voodoo? Can you grab the Hub Context from another process?!

mdevilliers commented 11 years ago

You should be able to broadcast to specific groups - although I haven't tried it.

You do need to access to the Hub class definition - if you look in the solution I've added the ChatHub.cs as a reference to both the Console project as well as the Web project.

Essentially the console application isn't connecting to the web application just broadcasting messages that end up on the shared message bus.

It isn't voodoo just total awesomeness - that David Fowler is pretty clever!