Communication between MDrivenServers
(Adding page to Category:TOC because it contains a TOC.)
 
(11 intermediate revisions by 4 users not shown)
Line 1: Line 1:
If you build a whole (micro) service universe you will soon notice a need for events triggered from one system sent to another.
=== Background ===
If you build a whole (micro) service universe, you will soon notice a need for events triggered from one system sent to another.


This can - and is - often handled as Rest-api's on two systems that call each other. While this strategy may get the job done you have an issue with the fact that the two systems must know about each other - and this quickly turns into a spaghetti tangled web of services that cannot really change without breaking something.
This can - and is - often handled as Rest-api's on two systems that call each other. While this strategy may get the job done, you have an issue with the fact that the two systems must know about each other - and this quickly turns into a spaghetti-tangled web of services that cannot change without breaking something.  


A much better approach is to have the more generic of the two systems expose a generic callback - an event.
A much better approach is to have the more generic of the two systems expose a generic callback - an event.


Such events are best implemented by an open socket that can be used by the generic system to signal events even if it knows nothing about the listener - that in turn may cause action in the caller.
=== Events ===
 
==== SignalR ====
Such events are best implemented by an open socket that can be used by the generic system to signal events even if it knows nothing about the listener, which in turn may cause action in the caller.


In .net SignalR is implementing this infrastructure.
In .net SignalR is implementing this infrastructure.


In MDrivenServer we use SignalR to enable internet signaling and event sending to subscribers  
In MDrivenServer, we use SignalR to enable internet signaling and event sending to subscribers  
 
[[Turn on websocket in IIS|Turn on websocket in IIS]]


==== RealtimeSubscribeToEvent ====
==== RealtimeSubscribeToEvent ====
Create an action column on a serverside ViewModel named RealtimeSubscribeToEvent. You will need these columns:
Create an action column on a serverside ViewModel named RealtimeSubscribeToEvent. You will need these columns:
* realtimehub = the MDrivenServer-url to the system to subscribe to - leave blank for THIS system
* realtimehub = the MDrivenServer-url to the system to subscribe to - leave blank for THIS system
* eventguid = a unique id (as a string) that makes the this event unique on instance level - you will want to share this eventguid with the event sender - because that will make your eventcookie come back to your system in the ReceiveEvent(theEventGuid, theEventCookie) callback   
* eventguid = a unique id (as a string) that makes this event unique on instance level - you will want to share this eventguid with the event sender - because that will make your event cookie come back to your system in the ReceiveEvent(theEventGuid, theEventCookie) callback   
* eventcookie = what you want the server to send back on event - suggested value 'Viewmodel=SomeVM&RootId='+self.externalid
* eventcookie = what you want the server to send back on event - suggested value 'Viewmodel=SomeVM&RootId='+self.externalid
You can call RealtimeSubscribeToEvent multiple times - only the latest eventCookie will be kept. If you send in a blank eventCookie or an eventCookie=="endsubscription" the subscription will be removed from the server.
You can call RealtimeSubscribeToEvent multiple times - only the latest eventCookie for a server/eventguid combination will be kept. If you send in a blank eventCookie or an eventCookie=="endsubscription" the subscription will be removed from the server.


==== RealtimeTriggerEvent ====
==== RealtimeTriggerEvent ====
Create an action column on a serverside ViewModel named RealtimeTriggerEvent. You will need this column:
Create an action column on a serverside ViewModel named RealtimeTriggerEvent. You will need this column:
* eventguid = a unique id (as a string) that makes the this event unique on instance level - you want to share this eventguid with the event subscriber - no matter how many subscribers you have - they will receive their eventcookie
* eventguid = a unique id (as a string) that makes this event unique on the instance level - you want to share this eventguid with the event subscriber. No matter how many subscribers you have, they will receive their event cookie.
* eventdata = an optional string the sender can fill - not currently used by the receiver.
* eventRemoveAfterSend:bool = optional, default false. If true, the client will only be notified this one time.


==== The receiving MDrivenServer ====
==== The Receiving MDrivenServer ====
The receiving MDrivenServer will use the eventcookie that comes back when the event is triggered in the ReceiveEvent(theEventGuid, theEventCookie) and create an [[AsyncTicket|SysAsyncTicket]] with the ViewModel and RootId taken from the cookie.
The receiving MDrivenServer will use the event cookie that comes back when the event is triggered in the ReceiveEvent(theEventGuid, theEventCookie) to create a [[AsyncTicket|SysAsyncTicket]] with the ViewModel and RootId taken from the cookie.


If you have a non MDrivenServer as a event giver - and you want to hook up the MDrivenServer as an event listener - then the event sending system must allow for the following SignalR api to be called and sent:
If you have a non-MDrivenServer as an event publisher - and you want to hook up the MDrivenServer as an event listener - then the event publishing system must allow for the following SignalR API to be called with:
  method SubscribeToEvent(string eventguid,string clientcookie );
  method SubscribeToEvent(string eventguid,string clientcookie );
  event ReceiveEvent(string eventguid, string ClientCookie);
  event ReceiveEvent(string eventguid, string ClientCookie, string eventData);
 
==== The Event Sending MDrivenServer ====
The event publishing MDrivenServer will, upon executing the RealTimeTrigger serverside vm action, use the eventguid and call the ReceiveEvent that will filter out the connected listening clients on eventguid - and send the clientcookie and eventData.
 
If you build another non-MDrivenServer system that wants to consume events from an MDrivenServer, you must expect to receive this event on your connection:
event ReceiveEvent(string eventguid, string ClientCookie, string eventData);
In this, you must parse the ClientCookie you sent in on SubscribeToEvent and act as you see fit.


==== The event sending MDrivenServer ====
===== Security =====
The event sending MDrivenServer will upon executing the RealTimeTrigger serverside vm action use the eventguid and call the ReceiveEvent that will filter out the connected listening clients on eventguid - and send the clientcookie
The events are open and not authenticated. Do not send sensitive data over events. Use events to trigger a just-in-time RestGet that is protected by AccessGroups.


If you build another -non MDrivenServer - system that wants to consume events from an MDrivenServer you must allow for the following SignalR api:
=== Usecases ===
event ReceiveEvent(string eventguid, string ClientCookie);
and in this you must parse the ClientCookie you sent in on SubscribeToEvent and act as you see fit.


==== Usecases ====
===== Usecase #1: The Multisender =====
Suppose you have an IOT device collecting movement in an area. You want 250 other services to react to this detection urgently, but you want to avoid having 250 services polling the IOT device continuously because the device is not on a fast server and the network connection is slow. A much better solution is to let the IOT device signal when detection is done. A naïve implementation lets the 250 services register in the IOT device and has the IOT device roll through the list to try to connect to the clients one by one. This may fail because some of the clients are behind firewalls, and some have been decommissioned recently.


===== Usecase #1 the multisender =====
Better solution: We let the IOT device expose an eventguid that is "MovementDetected". All the 250 services call IOTDevice.SubscribeToEvent("MovementDetected", clientcookie). All the 250 listeners have their own way of reacting - all give different client cookies. On detection of movement, all the 250 get notified swiftly on an already open socket. Depending on the need, the client may follow up with an authenticated RestCall to the Device to get further details important to its function.
Suppose you have an IOT device collecting movement in an area. You want 250 other services to react to this detection urgently - but you want to avoid to have 250 services to poll the IOT device continuously because the device is not on a fast server and the network connection is slow. A much better solution is to let the IOT device signal when a detection is done. A naïve implementation lets the 250 services register in the IOT device - and have the IOT device roll through the list to try and connect to the clients one by one. This may fail because some of the clients are behind firewalls, and some has been decommissioned recently.  


Better solution: We let the IOT device expose an eventguid that is "MovementDetected". All the 250 services call IOTDevice.SubscribeToEvent("MovementDetected",clientcookie) - all the 250 listeners have their own way of reacting - so all give different clientcookies. On detection of movement all the 250 gets notified swiftly on an already open socket - and depending on need the client may follow up with an authenticated RestCall to the Device to get further details important for its function.
===== Usecase #2: The One-to-one Sender =====
Suppose you have a generic service converting open-document-standard-files (.odt) to pdfs. Your other 250 systems want to use this capability to produce pdfs, but they need continuous feedback to show to an eager user waiting to see the result. We want to avoid polling the pdf generator too much with "are you done yet" questions - at the same time, we do not want our user to wait 5 seconds too long.


===== Usecase #2 the one to one sender =====
We create a RestPost API on the Pdf-service that receives the raw data but also a guid-string that acts as our eventguid. Thereafter, we call RealtimeSubscribeToEvent giving the URL to the Pdf-service, the guid-string, and an event cookie that we define as 'Viewmodel=DoThisWhenSomethingImportantHappendWithMyPDF&RootId='+self.externalid. We can then forget about this job and wait for the DoThisWhenSomethingImportantHappendWithMyPDF serverside ViewModel to be executed. This will probably pull the finished Pdf from the service and signal the user with an update of a [[SignalR and Realtime|real-time]] tagged attribute that updates immediately if someone is watching it. No network use during the wait and no unnecessary waiting done.
Suppose you have a generic service converting open-document-standard-files (.odt) to pdf's. Your other 250 systems want to use this capability to produce pdf's - but they need continuous feedback to show to an eager user waiting to see the result. We want to avoid polling the pdf generator to much with "are you done yet" questions but at the same time we do not want our user to wait 5 seconds to long.
[[Category:MDriven Server]]
{{Edited|July|12|2024}}


We create an RestPost api on the Pdf-service that receives the raw data but also a guid-string that act as our eventguid. Directly there after we call RealtimeSubscribeToEvent giving the url to the Pdf-service, the guid-string and a eventcookie that we define as 'Viewmodel=DoThisWhenSomethingImportantHappendWithMyPDF&RootId='+self.externalid. We can then just forget about this job and wait for the DoThisWhenSomethingImportantHappendWithMyPDF serverside ViewModel being executed. This will probably pull the finished Pdf from the service - and signal the user with an update of a [[SignalR and Realtime|realtime]] tagged attribute - that updates immediately if someone is watching it. No network use during wait - and no un-necessary waiting done.
[[Category:TOC]]

Latest revision as of 13:45, 26 March 2024

Background

If you build a whole (micro) service universe, you will soon notice a need for events triggered from one system sent to another.

This can - and is - often handled as Rest-api's on two systems that call each other. While this strategy may get the job done, you have an issue with the fact that the two systems must know about each other - and this quickly turns into a spaghetti-tangled web of services that cannot change without breaking something.

A much better approach is to have the more generic of the two systems expose a generic callback - an event.

Events

SignalR

Such events are best implemented by an open socket that can be used by the generic system to signal events even if it knows nothing about the listener, which in turn may cause action in the caller.

In .net SignalR is implementing this infrastructure.

In MDrivenServer, we use SignalR to enable internet signaling and event sending to subscribers

Turn on websocket in IIS

RealtimeSubscribeToEvent

Create an action column on a serverside ViewModel named RealtimeSubscribeToEvent. You will need these columns:

  • realtimehub = the MDrivenServer-url to the system to subscribe to - leave blank for THIS system
  • eventguid = a unique id (as a string) that makes this event unique on instance level - you will want to share this eventguid with the event sender - because that will make your event cookie come back to your system in the ReceiveEvent(theEventGuid, theEventCookie) callback
  • eventcookie = what you want the server to send back on event - suggested value 'Viewmodel=SomeVM&RootId='+self.externalid

You can call RealtimeSubscribeToEvent multiple times - only the latest eventCookie for a server/eventguid combination will be kept. If you send in a blank eventCookie or an eventCookie=="endsubscription" the subscription will be removed from the server.

RealtimeTriggerEvent

Create an action column on a serverside ViewModel named RealtimeTriggerEvent. You will need this column:

  • eventguid = a unique id (as a string) that makes this event unique on the instance level - you want to share this eventguid with the event subscriber. No matter how many subscribers you have, they will receive their event cookie.
  • eventdata = an optional string the sender can fill - not currently used by the receiver.
  • eventRemoveAfterSend:bool = optional, default false. If true, the client will only be notified this one time.

The Receiving MDrivenServer

The receiving MDrivenServer will use the event cookie that comes back when the event is triggered in the ReceiveEvent(theEventGuid, theEventCookie) to create a SysAsyncTicket with the ViewModel and RootId taken from the cookie.

If you have a non-MDrivenServer as an event publisher - and you want to hook up the MDrivenServer as an event listener - then the event publishing system must allow for the following SignalR API to be called with:

method SubscribeToEvent(string eventguid,string clientcookie );
event ReceiveEvent(string eventguid, string ClientCookie, string eventData);

The Event Sending MDrivenServer

The event publishing MDrivenServer will, upon executing the RealTimeTrigger serverside vm action, use the eventguid and call the ReceiveEvent that will filter out the connected listening clients on eventguid - and send the clientcookie and eventData.

If you build another non-MDrivenServer system that wants to consume events from an MDrivenServer, you must expect to receive this event on your connection:

event ReceiveEvent(string eventguid, string ClientCookie, string eventData);

In this, you must parse the ClientCookie you sent in on SubscribeToEvent and act as you see fit.

Security

The events are open and not authenticated. Do not send sensitive data over events. Use events to trigger a just-in-time RestGet that is protected by AccessGroups.

Usecases

Usecase #1: The Multisender

Suppose you have an IOT device collecting movement in an area. You want 250 other services to react to this detection urgently, but you want to avoid having 250 services polling the IOT device continuously because the device is not on a fast server and the network connection is slow. A much better solution is to let the IOT device signal when detection is done. A naïve implementation lets the 250 services register in the IOT device and has the IOT device roll through the list to try to connect to the clients one by one. This may fail because some of the clients are behind firewalls, and some have been decommissioned recently.

Better solution: We let the IOT device expose an eventguid that is "MovementDetected". All the 250 services call IOTDevice.SubscribeToEvent("MovementDetected", clientcookie). All the 250 listeners have their own way of reacting - all give different client cookies. On detection of movement, all the 250 get notified swiftly on an already open socket. Depending on the need, the client may follow up with an authenticated RestCall to the Device to get further details important to its function.

Usecase #2: The One-to-one Sender

Suppose you have a generic service converting open-document-standard-files (.odt) to pdfs. Your other 250 systems want to use this capability to produce pdfs, but they need continuous feedback to show to an eager user waiting to see the result. We want to avoid polling the pdf generator too much with "are you done yet" questions - at the same time, we do not want our user to wait 5 seconds too long.

We create a RestPost API on the Pdf-service that receives the raw data but also a guid-string that acts as our eventguid. Thereafter, we call RealtimeSubscribeToEvent giving the URL to the Pdf-service, the guid-string, and an event cookie that we define as 'Viewmodel=DoThisWhenSomethingImportantHappendWithMyPDF&RootId='+self.externalid. We can then forget about this job and wait for the DoThisWhenSomethingImportantHappendWithMyPDF serverside ViewModel to be executed. This will probably pull the finished Pdf from the service and signal the user with an update of a real-time tagged attribute that updates immediately if someone is watching it. No network use during the wait and no unnecessary waiting done.

This page was edited 53 days ago on 03/26/2024. What links here