This is a simple example of how we set up reminder grains in Orleans and f#.
Here's the code so you can follow along
Grain interface
type IYourReminderGrain =
    inherit IGrainWithStringKey
    inherit IRemindable
    abstract member WakeUp : unit -> Task
We have 2 important parts here that will be implemented in the grain.
- 
IRemindable: This forces us to implement theReceiveReminderfunction. This is where the logic we want to execute each time the reminder gets triggered.
- 
WakeUp: This activates the grain so we can set up the reminder
Grain implementation
type YourReminderGrain() =
    inherit Grain()
    interface IYourReminderGrain with
        member this.WakeUp() = Task.CompletedTask
        member this.ReceiveReminder(reminderName, status) =
            Console.WriteLine(reminderName, status)
            Task.CompletedTask
    override _.OnActivateAsync(cancellationToken:CancellationToken) = 
        let _periodInSeconds = TimeSpan.FromSeconds 60
        let _dueInSeconds = TimeSpan.FromSeconds 60
        let _reminder = base.RegisterOrUpdateReminder(base.GetPrimaryKeyString(), _dueInSeconds, _periodInSeconds)
        base.OnActivateAsync(cancellationToken)
There are 2 important parts here
- Implement the IYourReminderGrain: TheWakeUpis simple as we do not want to do anything here.ReceiveRemindercontains our logic. What we want to execute on every trigger of the reminder. Here we are simply writing the reminder name to the console.
- Overriding OnActivateAsync: This is where we register the reminder and specify at what interval it should trigger at._periodInSecondsspecifies the time between triggers and_dueInSecondsspecifies how long to wait until the first trigger
Kicking off the reminder grain
In this example I do this by adding a hosted service GrainActivatorHostedService.
This is responsible for retrieving the reminder grain from the IGrainFctory and calling the WakeUp grain function
let! _ =
    _client
        .GetGrain<IYourReminderGrain>(Guid.NewGuid().ToString())
                    .WakeUp() 
That's it. To run the app just run
> sh run-silo-local.sh
or
> sh run-silo-docker.sh
You can also run it in your IDE or VS Code devcontainers
To verify everything is working correctly:
- Dashboard: http://localhost:8081
- Dashboard if running with Docker http://localhost:3000
This is part of the road-to-orleans project. Check it out
       PiotrJustyna
       / 
        road-to-orleans
      
        PiotrJustyna
       / 
        road-to-orleans
      
    
    This repository illustrates the road to orleans with practical, real-life examples. From most basic, to more advanced techniques.
road to orleans
This repository illustrates the road to orleans with practical, real-life examples such as .NET solutions. From most basic to more advanced techniques. The code is written using .NET 6 and was tested on macOS (Catalina 10.15.7) and, wherever docker is supported, Linux (Alpine 3.12).
build & run
- IDE: build + run (first the cluster, then the client)
- run-[client/silo]-[docker/local].sh
monitoring
Silo dashboards are available by default on localhost:8080 unless configured otherwise in the code/dockerfile/run-[client/silo]-[docker/local].sh. Additionally, Datadog APM support is illustrated in solution 3b.
code
  
    
      flowchart TD
…
Solution1(Solution1: One basic silo, no grains.)
Solution2(Solution2: One basic silo, one grain, one console client.)
Solution3(Solution3: One basic silo, one grain, one console client, <br/>everything containerized.)
Solution3a(Solution3a: Solution3 + grain persistence.)
Solution3b(Solution3b: Solution3 + datadog APM.)
Solution4(Solution4: First in-memory clustering example. <br/>Many silos, many clients.)
Solution5(Solution5: Solution4 where
 

 
    
Top comments (0)