Orleankka Documentation

repository·master·Indexed 19 days ago

https://github.com/orleanscontrib/orleankka

A functional extension for Microsoft Orleans that introduces a message-based actor model inspired by Akka and ProtoActor. Orleankka facilitates patterns such as CQRS, Event Sourcing, and Finite State Machines (FSM) through a zero-overhead API, switchable actor behaviors, and actor/proxy middlewares. The library is distributed via specialized NuGet packages including Orleankka (core), Orleankka.Client, Orleankka.Runtime, and Orleankka.TestKit for unit testing.

Tokens
3.1K
Snippets
10
Records
15
Agent score
67%

What's inside Orleankka

  1. What is Orleankka?

    master

    Orleankka is a functional extension for the Microsoft Orleans framework. It provides a message-based API inspired by Akka and ProtoActor, layered on top of Orleans. It is designed for use-cases requiring composable, uniform communication interfaces, such as:

    • CQRS (Command Query Responsibility Segregation)
    • Event Sourcing
    • FSM (Finite State Machines)

    Key features include a zero-overhead message-based API, switchable actor behaviors (hierarchical FSM), background task management (jobs), actor/proxy middlewares (interceptors), and a dedicated unit testing kit.

  2. Define message types for Orleankka actors

    master

    In Orleankka, actors communicate via message types. These classes act similarly to object-oriented interface signatures (e.g., Greet(string who)). Every message type must be marked with the [Serializable] attribute to ensure they can be transmitted across the cluster.

    [Serializable]
    public class Greet
    {
        public string Who { get; set; }
    }
    
    [Serializable]
    public class Sleep
    {}
  3. Understand the Topic Retry and Error Handling Logic

    master

    The Topic actor manages search failures using a local retry mechanism and persistent reminders. The following logic governs how a Topic handles an unavailable Api:

    • Initial Failure: When a Topic receives its first failed reply from an Api, it schedules a local timer to retry the request every 5 seconds.
    • Consecutive Failures: If the Api remains unavailable for 3 consecutive retries, the Topic must:
      1. Disable search for that Api (by deleting the persistent reminder).
      2. Cancel the local retry timer.
    • Recovery during Retries: If the Api becomes available again while the Topic is in its retry loop, the Topic should cancel the local retry timer and resume normal scheduled searches.
    • Scheduled Execution:
      • If the Topic is in a 'retry state', it should ignore incoming scheduled search requests from persistent reminders.
      • Otherwise, it should proceed with the search request to the Api.
  4. Understand the Domain Model and Actors in the Demo Application

    master

    The Demo application is designed for continuous monitoring of social networks by creating topics of interest that trigger queries against vendor search APIs. The system is modeled using three primary actor types:

    1. Api (Singleton Actor): One instance per search provider (social network). It performs the actual search requests and implements the Circuit Breaker pattern. It can 'lock' itself during outages to prevent unnecessary requests and notifies subscribers when availability changes.
    2. Topic (User-defined Actor): Executes user-specified queries against specific APIs on a recurrent schedule. It aggregates results and manages its own execution schedule.
    3. SystemConsole (External Client): Monitors the availability of the Api actors by subscribing to their notifications. It allows administrators to manually re-enable searches for a specific Api if needed.
  5. Configure and run an Orleankka Silo and Client

    master

    To run an Orleankka application, you must configure both the Orleans Silo (server) and the Orleankka Client.

    1. Silo Setup: Use SiloHostBuilder, configure clustering, and call .UseOrleankka() to register the Orleankka extension.
    2. Client Setup: Use ClientBuilder, configure the cluster to match the Silo, and call .UseOrleankka().
    3. Interaction: Use client.ActorSystem() to get the system instance, then use system.ActorOf<T>(id) to get a proxy reference to a specific actor instance.
    // Silo Configuration
    var host = await new SiloHostBuilder()
        .Configure(options => {
            options.ClusterId = "localhost-demo";
            options.ServiceId = "localhost-demo-service";
        })
        .UseDevelopmentClustering(options => options.PrimarySiloEndpoint = new IPEndPoint(IPAddress.Loopback, 11111))
        .ConfigureEndpoints(IPAddress.Loopback, 11111, 30000)
        .ConfigureApplicationParts(x => x.AddApplicationPart(Assembly.GetExecutingAssembly()).WithCodeGeneration())
        .UseOrleankka()
        .Build();
    
    await host.StartAsync();
    
    // Client Configuration
    var client = new ClientBuilder()
        .ConfigureCluster(options => {
            options.ClusterId = "localhost-demo";
            options.ServiceId = "localhost-demo-service";
        })
        .UseStaticClustering(options => options.Gateways.Add(new IPEndPoint(IPAddress.Loopback, 30000).ToGatewayUri()))
        .ConfigureApplicationParts(x => x.AddApplicationPart(Assembly.GetExecutingAssembly()).WithCodeGeneration())
        .UseOrleankka()
        .Build();
    
    await client.Connect();
    
    // Using the Actor
    var system = client.ActorSystem();
    var greeter = system.ActorOf<IGreeter>("id");
    
    // Ask (Query)
    var response = await greeter.Ask<string>(new Greet { Who = "world" });
    
    // Tell (Command)
    await greeter.Tell(new Sleep());
  6. Explore Orleankka examples and patterns

    master

    Since the official documentation is undergoing an overhaul, the best way to learn the API is by examining the provided samples in the repository. Key patterns demonstrated include:

    • Hello World: Basic implementation.
    • Event Sourcing: Includes idiomatic CQRS patterns and persistence implementations using GetEventStore or Streamstone.
    • Finite State Machines (FSM): Demonstrates switchable behaviors, ranging from basic FSMs to durable FSMs with supervision (Process Managers).
    • Concurrency & Messaging: Examples of reentrant messages, client-side observers, and streams.
    • Testing: Usage of the TestKit for unit testing.
  7. Use Open Iconic's Icon Font with Bootstrap

    master

    To use Open Iconic with Bootstrap, include the Bootstrap-specific stylesheet and use the oi oi-icon-name class pattern.

    Setup: Include the CSS file located at font/css/open-iconic-bootstrap.{css, less, scss, styl}.

    Usage:

    <span class="oi oi-icon-name" title="icon name" aria-hidden="true"></span>
    <link href="/open-iconic/font/css/open-iconic-bootstrap.css" rel="stylesheet">
    <span class="oi oi-icon-name" title="icon name" aria-hidden="true"></span>
  8. Install Orleankka client or runtime via NuGet

    master

    Depending on whether you are building a client or a server-side implementation, install the appropriate NuGet package using the Package Manager Console:

    For Client-side usage: Use Orleankka.Client.

    For Server-side usage: Use Orleankka.Runtime.

    # Client-side library
    Install-Package Orleankka.Client
    
    # Server-side library
    Install-Package Orleankka.Runtime
  9. Use Open Iconic's Icon Font standalone

    master

    If you are not using Bootstrap or Foundation, use the default Open Iconic stylesheets.

    Setup: Include the CSS file located at font/css/open-iconic.{css, less, scss, styl}.

    Usage: Use the oi class and the data-glyph attribute to specify the icon.

    <span class="oi" data-glyph="icon-name" title="icon name" aria-hidden="true"></span>
    <link href="/open-iconic/font/css/open-iconic.css" rel="stylesheet">
    <span class="oi" data-glyph="icon-name" title="icon name" aria-hidden="true"></span>
  10. Implement an Orleankka actor

    master

    To create an actor, you must define a custom interface that inherits from IActorGrain and a class that inherits from ActorGrain and implements that interface. The core logic resides in the Receive method, where you use pattern matching to handle different message types.

    • Use Result(value) to return a response to a query (Ask).
    • Use TaskResult.Done for commands that do not return a value (Tell).
    • Return Unhandled if a message type is not recognized.
    using Orleankka;
    
    public interface IGreeter : IActorGrain {}
    
    public class Greeter : ActorGrain, IGreeter
    {
        public override Task<object> Receive(object message)
        {
            switch (message)
            {
                case Greet greet:
                    return Result($"Hello, {greet.Who}!");
    
                case Sleep _:
                    Console.WriteLine("Sleeeeping ...");
                    return TaskResult.Done;
    
                default:
                    return Unhandled;
            }
        }
    }