Akka.Persistence.Reminders
0.2.0
See the version list below for details.
dotnet add package Akka.Persistence.Reminders --version 0.2.0
NuGet\Install-Package Akka.Persistence.Reminders -Version 0.2.0
<PackageReference Include="Akka.Persistence.Reminders" Version="0.2.0" />
paket add Akka.Persistence.Reminders --version 0.2.0
#r "nuget: Akka.Persistence.Reminders, 0.2.0"
// Install Akka.Persistence.Reminders as a Cake Addin #addin nuget:?package=Akka.Persistence.Reminders&version=0.2.0 // Install Akka.Persistence.Reminders as a Cake Tool #tool nuget:?package=Akka.Persistence.Reminders&version=0.2.0
Akka.Persistence.Reminders
An Akka.NET scheduler designed to work with long running tasks. When compared to standard ActorSystem
scheduler, there are two major differences:
- Standard scheduler state is stored in memory. That means, it's going to be lost after
ActorSystem
or machine restart. Reminder state is backed by an Akka.Persistence eventsourcing engine, which means that it's able to survive between restarts, making it good choice for tasks designed to be fired hours, days or many weeks in the future. - Unlike standard scheduler, reminder is not designed to work with sub-second latencies. If this is your case, don't use reminders.
Basic example
var config = ConfigurationFactory.Load().WithFallback(Reminder.DefaultConfig);
using (var system = ActorSystem.Create("system", config))
{
// create a reminder
var reminder = system.ActorOf(Reminder.Props(), "reminder");
var taskId = Guid.NewGuid().ToString();
// setup a message to be send to a recipient in the future
var task = new Reminder.Schedule(taskId, recipient.Path, "message", DateTime.UtcNow.AddDays(1));
// setup a message to be send in hour intervals
var task = new Reminder.ScheduleRepeatedly(taskId, recipient.Path, "message", DateTime.UtcNow.AddDays(1), TimeSpan.FromHours(1));
// setup a message to be send at 10:15am on the third Friday of every month
var task = new Reminder.ScheduleCron(taskId, recipient.Path, "message", DateTime.UtcNow.AddDays(1), "15 10 ? * 6#3");
reminder.Tell(task);
// get scheduled entries
var state = await reminder.Ask<Reminder.State>(Reminder.GetState.Instance);
// cancel previously scheduled entity - if ack was defined it will be returned to sender after completion
reminder.Tell(new Reminder.Cancel(taskId))
}
You can also define a reply message, that will be send back once a scheduled task has been persisted.
var task = new Reminder.Schedule(Guid.NewGuid().ToString(), recipient.Path, "message", DateTime.UtcNow.AddDays(1), ack: "reply");
var ack = await reminder.Ask<string>(task); // ack should be "reply"
Cron Expressions
You can setup schedule to repeat itself accordingly to following cron expressions format:
Allowed values Allowed special characters
┌───────────── minute 0-59 * , - /
│ ┌───────────── hour 0-23 * , - /
│ │ ┌───────────── day of month 1-31 * , - / L W ?
│ │ │ ┌───────────── month 1-12 or JAN-DEC * , - /
│ │ │ │ ┌───────────── day of week 0-6 or SUN-SAT * , - / # L ?
│ │ │ │ │
* * * * *
Other characteristics (supported by a Cronos library used by this plugin):
- Supports non-standard characters like L, W, # and their combinations.
- Supports reversed ranges, like 23-01 (equivalent to 23,00,01) or DEC-FEB (equivalent to DEC,JAN,FEB).
- Supports time zones, and performs all the date/time conversions for you.
- Does not skip occurrences, when the clock jumps forward to Daylight saving time (known as Summer time).
- Does not skip interval-based occurrences, when the clock jumps backward from Summer time.
- Does not retry non-interval based occurrences, when the clock jumps backward from Summer time.
Using reminder in cluster
Since a reminder is a persistent actor, it's crucial, that only one instance of it may be active in the entire cluster at the same time. In order to avoid risk of having multiple instances or rellying on a single preconfigured machine, you may combine reminder together with Akka.NET cluster singleton from Akka.Cluster.Tools package.
system.ActorOf(ClusterSingletonManager.Props(
singletonProps: Reminder.Props(),
terminationMessage: PoisonPill.Instance,
// use role to limit reminder actor placement only to some subset of nodes
settings: ClusterSingletonManagerSettings.Create(system).WithRole("reminder")),
name: "reminder");
Using reminders together with Akka.Cluster.Sharding
Since sharded actors don't have a single ActorPath
as they can move between different nodes of the cluster, it's not reliable to set that actor's path as a reminder recipient. In this case a recipient should be the shard region living on a current cluster node, while the message itself should be a shard envelope having an information necessary to route the payload to target sharded actor.
var region = ClusterSharding.Get(system).Start(
typeName: "my-actor",
entityProps: Props.Create<MyActor>(),
settings: ClusterShardingSettings.Create(system),
messageExtractor: new MessageExtractor());
var envelope = new Envelope(shardId: 1, entityId: 1, message: "hello");
var task = new Reminder.Schedule(taskId, region.Path, envelope, DateTime.UtcNow.AddDays(1));
reminder.Tell(task);
Configuration
akka.persistence.reminder {
# Persistent identifier for event stream produced by correlated reminder.
persistence-id = "reminder"
# Identifier of a event journal used by correlated reminder.
journal-plugin-id = ""
# Identifer of a snapshot store used by correlated reminder.
snapshot-plugin-id = ""
# Unlike standard akka.net scheduler, reminders work in much lower frequency.
# Reason for this is that they are designed for a long running tasks (think of
# seconds, minutes, hours, days or weeks).
tick-inverval = 10s
# Reminder uses standard akka.persistence eventsourcing for maintaining scheduler
# internal state. In order to make a stream of events shorter (and ultimately
# allowing for a faster recovery in case of failure), a reminder state snapshot is
# performed after a series of consecutive events have been stored.
snapshot-interval = 100
}
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp1.0 was computed. netcoreapp1.1 was computed. netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard1.6 is compatible. netstandard2.0 was computed. netstandard2.1 was computed. |
.NET Framework | net45 is compatible. net451 was computed. net452 was computed. net46 was computed. net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen30 was computed. tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.5
- Akka.Persistence (>= 1.3.10)
- Cronos (>= 0.7.0)
-
.NETStandard 1.6
- Akka.Persistence (>= 1.3.10)
- Cronos (>= 0.7.0)
- NETStandard.Library (>= 1.6.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Added support for cron expressions.