Microsoft Orleans - Observables
As we continue exploring Microsoft Orleans — the virtual actor model framework — we happen upon Observers. Observers can be used to “observe” events, in the form of notifications, as an example.
Microsoft Orleans — Observers
Orleans observers are build by creating an interface that implements the Orleans’ namespaces’ IGrainObserver
interface. Observer methods must have a void return type, and can be invoked via a grain when “something” happens, in the form of a method call.
The Orleans Observers documentation can be found:
Observers | Microsoft Orleans Documentation
What we’ll need
There are a few steps to setting up an observer and a grain that can manage observers:
- New interface that implements
IGrainObserver
, and a class the implements the new interface. - A new grain interface and grain that provide a subscribe, unsubscribe, and notify like method.
- A class to manage registered observers.
- A method of using the above observer.
New interface implementing IGrainObserver
To hopefully go for the most straightforward observer, we’ll create an interface (and eventually class) that simply takes in a string message. This interface will look like:
1 |
|
In the above, we have a single method that takes in a string named message. This interface will act as our “observer” interface. As you can see this interface is quite simple — the only constraints being observer methods need to have a return type of void and the interface itself must implement the built in Orleans type of IGrainObserver
.
New grain interface for observables
Next, we’ll need a grain interface that can handle the registering and unregistering of observers, along with a method that should be used to “notify” the registered observers of the intended to be observed event.
1 |
|
Again pretty straightforward — we have a Subscribe
and Unsubscribe
method that take in an IObserverSample
(the interface from the previous step), and a SendMessageToObservers
, which, strangely enough, can be used to send messages to registered observers.
A class to manage registered observers
The documentation called out using a built in class ObserverSubscriptionManager
to assist with managing observers, however this class was apparently moved into a legacy assembly. The class could still be found in some of the Orleans samples, and here is that class with a few tweaks:
1 |
|
Note, the original class I found on the Orleans github repo (under their samples):
New Grain Implementation
we have all the groundwork and abstractions created for our observer/observable — now we need concretions for those interfaces.
The one new grain being introduced handles the sub/unsubbing, as well as notification “event” to the subscribed observers. This grain should look relatively familiar:
1 |
|
In the above, the only new thing not covered before (pretty sure) is the overriding of OnActivateAsync
. In this method, we’re newing up the _subsManager
and proceeding with the base implementation.
The Subscribe
and Unsubscribe
methods register or remove the passed in IObserverSample
from the GrainObserverManager
, while the Notify
method sends the event notification to all subscribed observers.
New IOrleansFunctions
In this demo, two new IOrleansFunctions
are to be introduced. One of the functions will be used as an observer, and the other will be used to send messages to that observer.
Starting with the simpler of the two, the event sender:
1 |
|
In the above, we’re using one of the three methods from the grain interface defined earlier. From here, we’re just utilizing the function to send user entered messages to our subscribed observers (if any exist).
How do we get observers to exist? That can be accomplished with the second IOrleansFunction
.
1 |
|
A few new things happening in the above IOrleansFunction
. First, our PerformFunction
method is being used to occasionally subscribe to our observer manager grain — this is done as sort of a “heartbeat” to keep the observer alive. I don’t think it has to be done this way, but working with the sample code from the documentation, this seemed to work out ok. I guess the alternative is not having observers expire, and keeping them around indefinitely? In the above, we’re doing our normal GetGrain call, but additionally, we’re setting this as an observer reference, to be registered with the observer manager.
The other method ReceiveMessage
is the method being implemented from the IObserverSample
. This method is the handler for what happens when the Notify
from the observer manager is called.
Demoing the observer
Now all that’s left is to run the application and make sure it works! For this demo we’ll as usual run the silohost and client, though this time we’ll actually be running two clients. One client will be used as the observer, and the other will be used to send a message to the observer. What does this look like?
Code as of this post can be found here:
Kritner-Blogs/OrleansGettingStarted
Related:
- Getting Started with Microsoft Orleans
- Microsoft Orleans — Reusing Grains and Grain State
- Using polymorphism to update Orleans Project to be ready for new Orleans Examples!
- Microsoft Orleans — Reporting Dashboard
- Microsoft Orleans — Code Generation Issue
- Microsoft Orleans — Dependency Injection
- Microsoft Orleans — Reminders and Grains Calling Grains
- Microsoft Orleans — Easily switching between “development” and “production” configurations.
- .net core console application IOptions
configuration - Microsoft Documentation — Orleans Observers
- Code as of post — https://github.com/Kritner-Blogs/OrleansGettingStarted/releases/tag/v0.55
- Photo by @freddymarschall on Unsplash.
Microsoft Orleans - Observables
https://blog.kritner.com/2019/01/16/Microsoft-Orleans-Observables/