I'm using SignalR in a prototype I'm building. I need to broadcast messages to a number of clients, but there is some logic as to which clients will get which message which is complex enough to rule out using Groups. Instead, I'm basically checking each connected client - if they are applicable, they're added to a List<>. I then send the message using:
var clients = DetermineClients(msg);
foreach (var client in clients)
client.Send(msg);
Of course, if I were able to use Groups, I could do...:
var group = DetermineGroup(msg);
group.Send(msg);
... since the 'Send' method of group appears to basically do the same thing - enumerate the clients in the group and call 'Send' on those. Is this the 'correct' way to do this? Or is there some way to create a temporary group on the fly? The 'dynamic' type of a group or singular client makes it difficult for me to determine whether I'm doing this right. If there is some magic going on behind the scene for optimising a broadcast to a number of clients, I'd obviously rather use that!
Any advice would be appreciated. Let me know if you need more info.
If you're simply trying to send the same message to a number of different clients based on a complex criteria your best bet would be to have a group that contains all of your clients and then query to find out which clients DO NOT fit your criteria. With the list of connection IDs that do not fit your criteria you can do:
Clients.Group("myGroupThatHasAllMyClients",myExcludedConnectionIds).bar();
Related
I am looking at using Signal R for my system
Each user of my system watches a small set of data.
For example, Fred smith (UserID 1) may want to know the price of Gold
UserID 2 wants to know the price of Gold and Silver
Throughout the day there will be hundreds of prices passing through the market
As a new price comes through my system, I am thinking of looking at the users logged in and seeing if any of them care about the price that has come in
If the user cares, I want to send the price to the client instance
I dont want to notify all Signal R clients when every price comes in as that would be too much data!
I am assuming this relies on being able to store something generated client side then passing it through with the connection to the hub
Does Signal R support this? I cant see anything obvious?
I have complete control over my hub.
At present, I plan to write data into a database which I use SQL dependancy to trigger the hub into action
I am using Signal R within MVC 5
Cheers
Paul
Possiblity A) Use Groupping mechanisme of signalR
I suggest you to create a group for each "item" (gold, silver,....).
In the case a user logs in, you should look in which items he is
interested and subscribe for these groups.
(Groups.Add(...) in your hub methode)
So in the case a the value of a item changes, you can send the new
value to all subscribers (clients which are interested to a group)
Clients.Group(groupName).newItemValue(YOURIDEMID, YOURNEWVALUE);
More details about groupping with signalr you will find here:
https://learn.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/working-with-groups
Possiblity B) Handle by yourself
In the case a client connects to the server save the id of this client. Also go to your database and show the interested items for this client. --> Finally you should have a dictionary which contains the ids of connected clients (id) and as value a list with the interested items.
In the case a value of an item changes you iterate through all connected clients and search clients which are iterested about that item. Finally send them the new value.
very new to signalR, and have rolled up a very simple app that will take questions for moderation at conferences (felt like a straight forward use case)
I have 2 hubs at the moment:
- Question (for asking questions)
- Speaker (these should receive questions and allow moderation, but that will come later)
Solution lives at https://github.com/terrybrown/InterASK
After watching a video (by David Fowler/Damian Edwards) (http://channel9.msdn.com/Shows/Web+Camps+TV/Damian-Edwards-and-David-Fowler-Demonstrate-SignalR)
and another that I can't find the URL for atm, I thought I'd go with 'groups' as the concept to keep messages flowing to the right people.
I implemented IConnected, IDisconnect as I'd seen in one of the videos, and upon debugging I can see Connect fire (and on reload I can see disconnect fire), but it seems nothing I do adds a person to a group.
The signalR documentation suggests "Groups are not persisted on the server so applications are responsible for keeping track of what connections are in what groups so things like group count can be achieved" which I guess is telling me that I need to keep some method (static or otherwise?) of tracking who is in a group?
Certainly I don't seem able to send to groups currently, though I have no problem distributing to anyone currently connected to the app and implementing the same JS method (2 machines on the same page).
I suspect I'm just missing something - I read a few of the other questions on here, but none of them seem to mention IConnected/IDisconnect, which tells me these are either new (and nobody is using them) or that they're old (and nobody is using them).
I know this could be considered a subjective question, though what I'm looking for is just a simple means of managing the groups so that I can do what I want to - send a question from one hub, and have people connected to a different hub receive it - groups felt the cleanest solution for this?
Many thanks folks.
Terry
As you seem to understand, which groups a logical connection (user if you will) is in is something you the application writer is responsible for maintaining across network disconnects/reconnects. If you look at the way JabbR does this, it maintains the state of which "rooms" a user is in in its database. Upon reconnecting, a user's identity helps place the current connection back into the proper set of groups that represent the specific "rooms".
What I'm asking for may be different than a group push where the collection of clients normally remain relatively constant.
In a notification system, clients can create events that not all other clients are subscribed to. For example, a client indicates that they don't want to receive notifications of new logins, but wants to know when a new photo is published from only certain users. The combinations are endless, and created on the fly, so you can't do a group push.
On each event, a new collection of clients will be created that will receive a notification. Is there a way to accomplish this with a bulk push rather than individual private messages?
Would the way to implement this be to create groups on the fly (on the server side), add clients to that group then send a message to that group?
Thanks.
I don't get why you need groups for this? Clients that subscribe to event foo via:
$.connection.myHub.foo = function() { }
Will be notified of the event. Where we aren't so good right now is with dynamically creating and removing events but that support will be improved.
If you want something dynamic, your only option would be to use groups.
Our program so far: We have a process that involves multiple schemata, orchestrations and messages sent/received.
Our desire: To have an ID that links the whole process together when we log our progress into a SQL server table.
So far, we have a table that logs our progress but when there are multiple messages it is very difficult to read since Biztalk will, sometimes, process certain messages out of order.
E.g., we could have:
1 Beginning process for client1
2 Second item for client1
3 Third item for client1
4 Final item for client1
Easily followed if there's only one client being updated at a time. On the other hand, this will be much more likely:
1 Beginning process for client1
2 Beginning process for client2
3 Second item for client2
4 Third item for client2
5 Second item for client1
6 Third item for client1
7 Final item for client1
8 Final item for client2
It would be nice to have an ID throughout the whole thing so that the last listing could ordered by this ID field.
What is the best and/or quickest way to do this? We had thought to add an ID, we would create, from the initial moment of the first orchestration's triggering and keep passing that value to all the schemata and later orchestrations. This seems like a lot of work and would require we modify all the schemata - which just seems wrong.
Should we even be wanting to have such an ID? Any other solutions that come to mind?
This may not exactly be the easiest way, but have you looked at this:
http://blogs.msdn.com/b/appfabriccat/archive/2010/08/30/biztalk-application-tracing-made-easy-with-biztalk-cat-instrumentation-framework-controller.aspx
Basically it's an instrumentation framework which allows you to event out from pipelines, maps, orchs, etc.
When you write out to the event-trace you can use a "business key" which will tie mutltiple events together in a chain, similar to what you are saying.
Available here
http://btscatifcontroller.codeplex.com/
I'm not sure I fully understand all the details of your specific setup, but here goes:
If you can correlate the messages from the same client into a "long running" orchestration (which waits for subsequent messages from the same client), then the orchestration will have an automatically assigned ServiceId Guid, which will be kept throughout the orchestration.
As you say, for correlation purposes, you would usually try and use natural keys within the existing incoming message schemas to correlate subsequent messages back to the running orchestration - this way you don't need to change the schemas. In your example, ClientId might be a good correlation, provided that the same client cannot send multiple message 'sets' simultaneously. (and worst case, if you do add a new correlation key to the schemas, all systems involved in the orchestration will need to be changed to 'remember' this key and return it to you.) Again, assuming ClientId as a correlation key, in your example, 2 orchestrations would be running simultaneously - one for Client 1 and one for Client 2
However, for scalability and version control reasons, (very) long running orchestrations are generally to be avoided unless they are absolutely necessary (e.g. unless you can only trigger a process once all 4 client messages are received). If you decide to keep each message as a separate orchestration or just mapped and filtered on a port, another way to 'track' the sets of is by using BAM - you can use a continuation to tie all the client messages back together, e.g. for the purpose of a report or such.
Take a look at BAM. It's designed to do exactly what you describe: Using Business Activity Monitoring
This book has got a very good chapter about BAM and this tool, by one of the authors of the book, can help you developing your BAM solution. And finally, a nice BAM Poster.
Don't be put off by the initial complexity. When you get your head around it, BAM it's one of the coolest features of BizTalk.
Hope this helps. Good luck.
Biztalk assigns various values in the message context that usually persist for the life of the processing of that message. Such as the initial MessageId. Will that work for you?
In our application we have to use an externally provided ID (from the customer). We have a multi-part message with this id in part of it. You might consider that as well
You could create a UniqueId and StepId and pass them around in the message context. When a new process for a client starts set UniqueId to a Guid and StepId to 1. As it gets passed to the next process increment the StepId.
This would allow you to query events, grouped by client id and in the order (stepId) the event happened.
I am trying to correlate an orchestration based on part of a received file location name and the date received. I have the receive port with an inbound map that assigns the date, but I cannot figure out out to access the promoted property for the receive location (which I have promoted).
Is there any way to access this info? Xpath? C# functoid?
Thanks!
Literally answering your question, yes, there is a C# functoid that allows access to the context properties from within a map.
However, if I understand your question correctly, you have an orchestration that sends a request message and is asynchronously waiting for a correlated response. I also understand that you would like all messages received from a specific Receive Location at a certain date to be routed back to the appropriate orchestration.
For this, you do not need to access promoted properties from within a map. All you have to do is initialize an appropriate Correlation when sending the message and have the properties specified in the Correlation Set promoted by the incoming Receive Pipeline.
For this to make sense, obviously, you would need to restrict the date to an acceptable range, with precision to a day, a hour-range or even a minute-range. Anything below that would run the risk of not being able to correlate the response to the appropriate time.
If you have some degree of control on the particular system that produces the response, using a GUID for the correlated property is probably the simplest approach.