How to implement user specific real-time data on blazor server? - asp.net-core

I've been trying for a few days, and struggling with a best practice for this - any ideas?
Contrived private message example:
Multiple users logged into blazor server
Server subscribes to an event bus/message queue to receive NewMessageEvent
Only the user that is the intended recipient should be updated.
I can create a singleton to subscribe to the message queue.
I can then use a singleton that I inject to the required blazor component to add the message to a list and issue a stateHasChanged event.
That would update all connected clients (not ideal, the service injected to the components should be scoped).
Options so far:
I could verify the recipient for the message inside the blazor component, but it sort of feels the wrong place
Subscribe to the queue once per circuit (The queue still holds all messages though)
What I was hoping to do, was possibly create a service locator based on the circuit Id and connected userId using a circuit handler, and call a function like: NewMessageReceivedFor(userId), if that finds a matched circuit, then call the scoped service function.
This means that I should call a scoped service from a singleton (not allowed by DI through the constructor), by some form of GetRequiredService, but can I get that scoped service by specifying a circuit Id?
I currently feel Im either 90% there, or in the wrong forest, let alone up the wrong tree.

You could have a Singleton service for dealing with all messages, and then a Scoped service that subscribes to an event on the Singleton and then only triggers its own event if the message is for the current user (you'd need a service registered as Scoped to get the current user ID).
That way each user will only get a notification when the message is meant for them.
Don't forget to implement IDisposable on the Scoped service, so you can unsubscribe from the Singleton service.

Related

All Endpoint Instances subscribe and handle event

I have a notification service that handles events and publishes them to clients using various technologies, such as SignalR. I want every instance of my notification service to pick up and handle these events. However, NServiceBus only allows any one instance of my notification service endpoint to pick up the event, and the other instances never get it.
My current workaround for this is to create a separate named endpoint for each instance of my notification service (the name has the server host name added to it), but then I have to make sure I unsubscribe from the event when the instance goes down or is moved to another server.
Is there a better way to do this? It would be nice if I could configure NServiceBus to create a separate incoming queue for each endpoint instance in this case, but I can't figure out how to do that, or even if NServiceBus supports such a use case.
You are correct. NServiceBus does not support such a case. Subscribers are always treated as logical endpoints, so individualized queues would not be used even if they were available.
Differentiating the instances by modifying the endpoint name is the most straightforward way to achieve what you want.
Changing your differentiator to a controllable runtime value, for instance an environment variable, would at least alleviate the need to unsubscribe when an instance is moved.
Also, if you want to review the scenario in more detail please don't hesitate to reach out to us directly, we might have other approaches to suggest. Just open a support ticket.

create WCF one-way (fire and forget) service out of XAMLX or how can a client call a service as one-way, if the operation is not defined one way

I am trying to create a XAMLX service that I can fire and forget.
But how can I do something like that with a XAMLX? I have no access to the Contract Interface to add the [OneWay] attribute.
I thought that if I did something like
and put the response before the rest of the activities, the service would return at that point but it didn't. It returns only after the whole workflow is completed.
IS it possible to make the service return at that point and than continue with the processing. the other activities would not affect the returned value of the service.
Is it possible to create a fire and forget XAMLX service
Can I somehow make the client fire a normal service as oneWay, if the previous 2 points are not possible?
If you want one-way processing your Receive activity should not have any corresponding SendReply activity.
The reason the response isn't send immediately is the way the workflow scheduler works internally where it waits for the workflow to go idle. Nothing much you can do about the scheduler but if you add a Delay below the SendResponse with a duration of 1 millisecond.
As Ladislav said, remove the SendResponse and you get a one way message.
Not quite sure what you want with fire and forget. If you start a workflow service it will keep on running even if you don't send any more WCF requests to it. Even if it is long running or does other async work. No problems there.

How a WCF request can be correlated with multiple Workflow instances?

The scenario is a follow:
I have multiple clients in which they can register themselves on a workflow server, using WCF requests, to receive some kind of notifications. The information of the notifications will be received from an external system using another receive activity. The workflow then should get the notification information and callback all registered clients using send activity and callback correlations (the clients are exposing callback interfaces implemented in there and the end-point addresses passed initially with the registration requests). "Log-running workflow service" approach is used with a persistent storage.
Now, I'm looking for some way to correlate the incoming information of the notifications received from the external system with the persisted workflow instances created previously when the registration requests, so that all clients will be notified using end-points that already passed with the registration requests. Is WF 4.0 capable of resuming and executing multiple workflow instances when the information of the notification received without storing end-points somehow manually and go though them? If yes, how can I do that?
Also, if my approach of doing so is not correct, then please advice me about the best practice of doing such system using WCF services.
Your help is highly appreciated.
When you use request correlation with workflow services the correlation key must always match a single workflow instance, you can't have multiple workflow instances react to a single message. So you either need to multicast the message using all the different correlation keys or resume you workflow instances in some other way. That other way could be to store the request somewhere, like a SQL table, and have the workflows periodically check that location if they need to notify the client.

NServiceBus, NHibernate, and GuidComb()

Disclaimer: This is a follow-on question from my other question about NServiceBus which was answered very thoroughly.
My current question is this: If a website is built to be 'dumb' like the article referred to, above, suggests then how does the following scenario work?
A user registers on a website by filling out a form with relevant details. When the user clicks the 'submit' button on the form the web application takes the form data and creates a message which it sends to the application tier using NServiceBus and Bus.Send(). The application tier goes about the business of creating the new user and publishing the event that the user has been created (Bus.Publish()) so that other processes can do their thing (email the new user, add the user to a search index, etc, etc).
Now, since the web application in this scenario relies entirely on the application tier for the creation of the new user instance, how does it get to know about the user's id? If I didn't use NServiceBus in this scenario but, rather, let the website issue an in-process call to a DAL I'd use NHibernate's GuidComb() strategy to create the identifier for the new user before persisting the new row in the database. If the message handler application which receives the command to create a new user (in the current scenario) uses the same strategy, how is the userId communicated back to the web application?
Do I have to apply a different strategy for managing identifiers in a scenario such as this?
You're free to come up with an ID to use as a correlation identifier by putting it in your message in the web application, allowing it to be carried around whatevery processes are initiated by the message.
That way, you can correlate the request with other events around your system, if only they remember to supply the correlation ID.
But it sounds like you want your user ID to be fed back to you in the same web request - that cannot easily be done with an asynchronous backend, which is what messaging gives you.
Wouldn't it be acceptable to send an email to the user when the user has been created, containing a (secret) link to some kind of gateway, that resumes the user's session?
Wouldn't the UI be able to listen to the bus for the "user created" event? And then you could correlate either by having the event include some kind of event ID linking back to the "user creation requested" event or against some other well known data in the event (like the user name). Though you probably also have to listen to multiple events, such as "user creation failure" event.
This is not unlike normal AJAX processing in a web browser. Technically, you don't block on the out of band call back to the web server. You invoke the call and you asynchronously wait for a callback.

WCF percall and single instance

I used this example to implement WCF service that fires events (using callback) to all clients when something happening on the service. The problem is that this example works only when the service instance is percall.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Reentrant)]
I want to use single instance but it won't work.It fires all the events to the last subscribed client.
Please help.
The sample has InstanceContextMode.PerSession, not InstanceContextMode.PerCall. Each subscribed client is associated with a separate instance of MyService. Each of these instances has a member field _callbackInstance which holds the reference to its particular client's callback channel. All the instances of MyService are associated into a "chat room" via the static event Broadcast, and when a particular client says something, the code iterates through the invocation list of the static event to broadcast to each subscribed client.
If you make MyService a singleton, _callbackInstance only contains the last subscribed client's callback channel, which is why you see the behaviour you describe.
In order to make the service class operate correctly as a singleton instance, you would have to replace _callbackInstance with a collection containing all the callback channels for the subscribed clients, and manage the additions and deletions from this collection yourself as clients arrived and left. Broadcasting would then involve iterating this collection. The drawback of this approach is that multiple clients may be calling the service concurrently, and you therefore need explicitly to synchronise access to the members of the class in order to ensure thread-safety and correct behaviour.
Thanks to Chris, I found this example showing how to handle multiply callback subscribers when using InstanceContextMode.Single. The example showing how to manage a dictionary (list is also possible) of callback channels.
Igal.