The Act in Modern Age
The word “Act” has a lot of meaning. The one we intend to use in this article is performance as in acting a role or persona at least in this introductory section. In modern times pervasive social media have anchored eyeballs 24×7 on performing artists or simply; “actors”. This has carved a mark on their personas. They now need to wear the act of their upcoming movie or series much longer than in the past days.
But then, this article is not about the method, phenomena, or life of actors and their acting. This is meant to be an article that takes a creative jab at a software programming topic. If you have survived enough in the industry, you would have got the cue (wink, wink). We are talking about the Actor design pattern.
Our copy director (the one responsible for this article!) has warned us and also washed our hands off the responsibility of this article because of our poor attempt at humour. But we thought it was worth a shot as software programmers have spent enough time in front of screens that the advancements of humour standards in stand-up performances are oblivious.
Much oblivious; compared to the advancements in the start-up landscape.
Alright, enough of jostling each other on this, let us get to the business and talk about Actors in Orleans (not the French “isle” within the bustling US of A).
Microsoft claims to have dug gold. They invented a virtual actor design pattern where the actor will have a life, longer than its run time. Perhaps without a performance penalty! Before we virtualise let us recap the Actor design pattern itself.
The actor
It is a thread-safe unit that can have a state of computation. It is capable of generating, and consuming messages. It can create new actors when needed. This was all in fashion in the early days of Object-Oriented programming. It lost its shine as time progressed. Over time, behaviour was introduced. It is a function that processes incoming messages. An Actor could specify a new behaviour for the message that it emits. Though the chrome of this design pattern lost its shine to new languages; the design pattern itself survived in those new languages just to be rediscovered.
Orleans
It is the distributed compute native framework that addresses the modern distributed application build challenges. Orleans builds upon the Actor design pattern and claims to have discovered the Virtual Actor design pattern. Along the way, the two simple concepts were introduced.
Grain
They are composites of identity, behaviour and state optionally. Identity gives the longevity to actors. This is; a contributing factor to the “Virtual” in virtual actor design pattern. The other contributing factor is the nature of the state. Grain can have a persistent or volatile state. This gives way for the framework to call for a grain when required. It is done based on their identity. They are removed from the memory when not needed.
Silo
The negative commotion that emerges on hearing this word is beyond description. Yet framework designers used this name for a concept in Orleans. They are equivalent to runtime. They can be grouped to create clusters. Clusters of runtimes host grain.
At this point, it is “virtually” impossible for us not to quote Kubernetes. The concepts in Orleans have a strange recall to those in the Kubernetes framework.
Expressing ourselves through code
Let us start Grain, since C# does not allow inheritance from multiple classes, we ought to go the Interface and Base class way. Something that is not an alien concept to you; isn’t it?
namespace Contracts; |
public interface IGreet: IGrainWithIntegerKey { |
ValueTask<string> SimpleGreeting(); |
} |
Next, we implement this contract in a class.
using Contracts; |
public class GreetGrain: Grain, IGreet { |
ValueTask<string> IGreet.SimpleGreeting() { |
return ValueTask<string>.FromResult(“I am a long running performer. Greetings to you, Thank you for instantiating me!”); |
} |
} |
Notice the return types. Modern digital native applications cannot assume they will run on a console by default. Thus, it is better to return a value; instead of printing a greeting message on the console. We cannot run this yet. We need to give a silo for this grain to run in.
using Microsoft.Extensions.Hosting; |
namespace Silo.Console { |
IHostBuilder builder = Host.CreateDefaultBuilder(args).UseOrleans(silo => silo.UseLocalhostClustering()).UseConsoleLifetime(); |
using IHost host = builder.Build(); |
await host.RunAsync(); |
} |
We are using C# 9.0+ syntax where the boilerplate code for static void main is unnecessary. Well; we cannot yet experience the Orleans in action. Though, we can run it. The result will be, a console application that waits for some action.
We ought to add a client that gets the greetings. It is in the client that we will instantiate a grain and use the services of Silo.
using Microsoft.Extensions.Hosting; |
using Microsoft.Extensions.DependencyInjection; |
using Contracts; |
namespace Actor.Client { |
IHostBuilder builder = Host.CreateDefaultBuilder(args).UseOrleansClient(client => client.UseLocalhostClustering()).UseConsoleLifetime(); |
using IHost host = builder.Build(); |
await host.StartAsync(); |
IClusterClient client = host.Services.GetRequiredService<IClusterClient>(); |
IGreet receptionist = client.GetGrain<IGreet>(); |
string greetings = await receptionist.SimpleGreeting(); |
Console.WriteLine(greetings); |
await host.StopAsync(); |
} |
In this simple example, we are using the Interface as an identity that could be used to locate the grain. We leave you with a puzzle. The silo did not say anything about the grain. How could it resolve IGreet when the client calls it?
Before we leave; doesn’t the application feel the same pressure in the modern day of cloud computing to be available and ready to serve quickly like an actor with pressure from social media? (The Copy director was cringing when he read this stanza 😊)
Until next time, happy coding.
Recent post
Archives
- November 2024
- October 2024
- September 2024
- August 2024
- July 2024
- June 2024
- October 2023
- June 2023
- March 2023
- February 2023
- January 2023
- December 2022
- November 2022
- October 2022
- September 2022
- August 2022
- July 2022
- June 2022
- May 2022
- April 2022
- March 2022
- February 2022
- January 2022
- December 2021
- November 2021
- October 2021
- September 2021
- August 2021
- July 2021
- June 2021
- May 2021
- April 2021
- January 2021
- December 2020
- October 2020
- August 2020
- June 2020
- May 2020
- April 2020
- March 2020
- February 2020
- January 2020
- December 2019
- November 2019
- October 2019
- September 2019
- August 2019
- July 2019
- June 2019
- May 2019
- April 2019
- March 2019
- February 2019
- January 2019