public Reminder(ReminderSettings settings) { this.UpdateState = e => { switch (e) { case Scheduled scheduled: this.state = state.AddEntry(scheduled.Entry); break; case Completed completed: this.state = state.RemoveEntry(completed.TaskId); break; } }; this.settings = settings; PersistenceId = settings.PersistenceId; JournalPluginId = settings.JournalPluginId; SnapshotPluginId = settings.SnapshotPluginId; tickTask = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(settings.TickInterval, settings.TickInterval, Self, Tick.Instance, ActorRefs.NoSender); Command <Tick>(_ => { var now = DateTime.UtcNow; foreach (var schedule in state.Entries.Values.Where(e => ShouldTrigger(e, now))) { Log.Info("Sending message [{0}] to recipient [{1}]", schedule.Message, schedule.Recipient); var selection = Context.ActorSelection(schedule.Recipient); selection.Tell(schedule.Message, ActorRefs.NoSender); Emit(new Completed(schedule.TaskId, now), UpdateState); var next = schedule.WithNextTriggerDate(now); if (next != null) { Emit(new Scheduled(next), UpdateState); } } }); Command <Schedule>(schedule => { var sender = Sender; try { Emit(new Scheduled(schedule.WithoutAck()), e => { UpdateState(e); //NOTE: use `schedule`, not `e` - latter contains a version with ACK explicitly erased to avoid storing ack in persistent memory if (schedule.Ack != null) { sender.Tell(schedule.Ack); } }); } catch (Exception error) { Log.Error(error, "Failed to schedule: [{0}]", schedule); if (schedule.Ack != null) { sender.Tell(new Status.Failure(error)); } } }); Command <GetState>(_ => { Sender.Tell(state); }); Command <Cancel>(cancel => { var sender = Sender; try { Emit(new Completed(cancel.TaskId, DateTime.UtcNow), e => { UpdateState(e); if (cancel.Ack != null) { sender.Tell(cancel.Ack); } }); } catch (Exception error) { Log.Error(error, "Failed to cancel task: [{0}]", cancel.TaskId); if (cancel.Ack != null) { sender.Tell(new Status.Failure(error)); } } }); Command <SaveSnapshotSuccess>(success => { Log.Debug("Successfully saved reminder snapshot. Removing all events before seqNr [{0}]", success.Metadata.SequenceNr); DeleteMessages(success.Metadata.SequenceNr - 1); }); Command <SaveSnapshotFailure>(failure => { Log.Error(failure.Cause, "Failed to save reminder snapshot"); }); Recover <Scheduled>(UpdateState); Recover <Completed>(UpdateState); Recover <SnapshotOffer>(offer => { if (offer.Snapshot is State state) { this.state = state; } }); }
/// <summary> /// An actor <see cref="Akka.Actor.Props"/> for <see cref="Reminder"/> class setup using provided <paramref name="settings"/>. /// </summary> public static Props Props(ReminderSettings settings) => Actor.Props.Create(() => new Reminder(settings));
public Reminder() : this(ReminderSettings.Create(Context.System.Settings.Config.GetConfig("akka.persistence.reminder"))) { }
public Reminder(ReminderSettings settings) { this.settings = settings; PersistenceId = settings.PersistenceId; JournalPluginId = settings.JournalPluginId; SnapshotPluginId = settings.SnapshotPluginId; tickTask = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(settings.TickInterval, settings.TickInterval, Self, Tick.Instance, ActorRefs.NoSender); Command <Tick>(_ => { var now = DateTime.UtcNow; foreach (var entry in state.Entries.Values.Where(e => ShouldTrigger(e, now))) { Log.Info("Sending message [{0}] to recipient [{1}]", entry.Message, entry.Recipient); var selection = Context.ActorSelection(entry.Recipient); selection.Tell(entry.Message, ActorRefs.NoSender); Emit(new Completed(entry.TaskId, now), UpdateState); if (entry.RepeatInterval.HasValue) { var next = now + entry.RepeatInterval.Value; Emit(new Scheduled(entry.WithNextTriggerDate(next)), UpdateState); } } }); Command <Schedule>(schedule => { var entry = new Entry(schedule.TaskId, schedule.Recipient, schedule.Message, schedule.TriggerDateUtc, schedule.RepeatInterval); var sender = Sender; Emit(new Scheduled(entry), e => { UpdateState(e); if (schedule.Ack != null) { sender.Tell(schedule.Ack); } }); }); Command <GetState>(_ => { Sender.Tell(state); }); Command <Cancel>(cancel => { var sender = Sender; Emit(new Completed(cancel.TaskId, DateTime.UtcNow), e => { UpdateState(e); if (cancel.Ack != null) { sender.Tell(cancel.Ack); } }); }); Command <SaveSnapshotSuccess>(success => { Log.Debug("Successfully saved reminder snapshot. Removing all events before seqNr [{0}]", success.Metadata.SequenceNr); DeleteMessages(success.Metadata.SequenceNr - 1); }); Command <SaveSnapshotFailure>(failure => { Log.Error(failure.Cause, "Failed to save reminder snapshot"); }); Recover <Scheduled>(scheduled => UpdateState(scheduled)); Recover <Completed>(completed => UpdateState(completed)); Recover <SnapshotOffer>(offer => { if (offer.Snapshot is State offerred) { state = offerred; } }); }