From 554086ccba07338194aca2a1eb8e0f9d801973b7 Mon Sep 17 00:00:00 2001 From: Gregorius Soedharmo Date: Tue, 24 Sep 2024 21:41:38 +0700 Subject: [PATCH] Add IWithTimers API with sender override (#7341) * Add IWithTimers API with sender override * Update API Approval list --- ...oreAPISpec.ApproveCore.DotNet.verified.txt | 3 + .../CoreAPISpec.ApproveCore.Net.verified.txt | 3 + .../Akka/Actor/Scheduler/ITimerScheduler.cs | 46 +++++++++++++ .../Akka/Actor/Scheduler/TimerScheduler.cs | 67 +++++++++++++++++-- 4 files changed, 113 insertions(+), 6 deletions(-) diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCore.DotNet.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCore.DotNet.verified.txt index 1b37b6e47af..60fa2406c64 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCore.DotNet.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCore.DotNet.verified.txt @@ -1183,8 +1183,11 @@ namespace Akka.Actor void CancelAll(); bool IsTimerActive(object key); void StartPeriodicTimer(object key, object msg, System.TimeSpan interval); + void StartPeriodicTimer(object key, object msg, System.TimeSpan interval, Akka.Actor.IActorRef sender); void StartPeriodicTimer(object key, object msg, System.TimeSpan initialDelay, System.TimeSpan interval); + void StartPeriodicTimer(object key, object msg, System.TimeSpan initialDelay, System.TimeSpan interval, Akka.Actor.IActorRef sender); void StartSingleTimer(object key, object msg, System.TimeSpan timeout); + void StartSingleTimer(object key, object msg, System.TimeSpan timeout, Akka.Actor.IActorRef sender); } public interface IUntypedActorContext : Akka.Actor.IActorContext, Akka.Actor.IActorRefFactory, Akka.Actor.ICanWatch { diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCore.Net.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCore.Net.verified.txt index 6a336c39672..eccf3f67d9b 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCore.Net.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCore.Net.verified.txt @@ -1181,8 +1181,11 @@ namespace Akka.Actor void CancelAll(); bool IsTimerActive(object key); void StartPeriodicTimer(object key, object msg, System.TimeSpan interval); + void StartPeriodicTimer(object key, object msg, System.TimeSpan interval, Akka.Actor.IActorRef sender); void StartPeriodicTimer(object key, object msg, System.TimeSpan initialDelay, System.TimeSpan interval); + void StartPeriodicTimer(object key, object msg, System.TimeSpan initialDelay, System.TimeSpan interval, Akka.Actor.IActorRef sender); void StartSingleTimer(object key, object msg, System.TimeSpan timeout); + void StartSingleTimer(object key, object msg, System.TimeSpan timeout, Akka.Actor.IActorRef sender); } public interface IUntypedActorContext : Akka.Actor.IActorContext, Akka.Actor.IActorRefFactory, Akka.Actor.ICanWatch { diff --git a/src/core/Akka/Actor/Scheduler/ITimerScheduler.cs b/src/core/Akka/Actor/Scheduler/ITimerScheduler.cs index b27bd2540b8..a8495e0dd01 100644 --- a/src/core/Akka/Actor/Scheduler/ITimerScheduler.cs +++ b/src/core/Akka/Actor/Scheduler/ITimerScheduler.cs @@ -35,6 +35,21 @@ public interface ITimerScheduler /// Interval void StartPeriodicTimer(object key, object msg, TimeSpan interval); + /// + /// Start a periodic timer that will send to the "Self" actor at + /// a fixed . + /// + ///Each timer has a key and if a new timer with same key is started + /// the previous is cancelled and it's guaranteed that a message from the + /// previous timer is not received, even though it might already be enqueued + /// in the mailbox when the new timer is started. + /// + /// Name of timer + /// Message to schedule + /// Interval + /// The sender override for the timer message + void StartPeriodicTimer(object key, object msg, TimeSpan interval, IActorRef sender); + /// /// Start a periodic timer that will send to the "Self" actor at /// a fixed . @@ -50,6 +65,22 @@ public interface ITimerScheduler /// Interval void StartPeriodicTimer(object key, object msg, TimeSpan initialDelay, TimeSpan interval); + /// + /// Start a periodic timer that will send to the "Self" actor at + /// a fixed . + /// + /// Each timer has a key and if a new timer with same key is started + /// the previous is cancelled and it's guaranteed that a message from the + /// previous timer is not received, even though it might already be enqueued + /// in the mailbox when the new timer is started. + /// + /// Name of timer + /// Message to schedule + /// Initial delay + /// Interval + /// The sender override for the timer message + void StartPeriodicTimer(object key, object msg, TimeSpan initialDelay, TimeSpan interval, IActorRef sender); + /// /// Start a timer that will send once to the "Self" actor after /// the given . @@ -64,6 +95,21 @@ public interface ITimerScheduler /// Interval void StartSingleTimer(object key, object msg, TimeSpan timeout); + /// + /// Start a timer that will send once to the "Self" actor after + /// the given . + /// + /// Each timer has a key and if a new timer with same key is started + /// the previous is cancelled and it's guaranteed that a message from the + /// previous timer is not received, even though it might already be enqueued + /// in the mailbox when the new timer is started. + /// + /// Name of timer + /// Message to schedule + /// Interval + /// The sender override for the timer message + void StartSingleTimer(object key, object msg, TimeSpan timeout, IActorRef sender); + /// /// Check if a timer with a given is active. /// diff --git a/src/core/Akka/Actor/Scheduler/TimerScheduler.cs b/src/core/Akka/Actor/Scheduler/TimerScheduler.cs index d82557a1c62..9f87efdc371 100644 --- a/src/core/Akka/Actor/Scheduler/TimerScheduler.cs +++ b/src/core/Akka/Actor/Scheduler/TimerScheduler.cs @@ -105,7 +105,25 @@ public TimerScheduler(IActorContext ctx) /// Interval public void StartPeriodicTimer(object key, object msg, TimeSpan interval) { - StartTimer(key, msg, interval, interval, true); + StartTimer(key, msg, interval, interval, true, ActorRefs.NoSender); + } + + /// + /// Start a periodic timer that will send to the "Self" actor at + /// a fixed . + /// + /// Each timer has a key and if a new timer with same key is started + /// the previous is cancelled and it's guaranteed that a message from the + /// previous timer is not received, even though it might already be enqueued + /// in the mailbox when the new timer is started. + /// + /// Name of timer + /// Message to schedule + /// Interval + /// The sender override for the timer message + public void StartPeriodicTimer(object key, object msg, TimeSpan interval, IActorRef sender) + { + StartTimer(key, msg, interval, interval, true, sender); } /// @@ -123,7 +141,26 @@ public void StartPeriodicTimer(object key, object msg, TimeSpan interval) /// Interval public void StartPeriodicTimer(object key, object msg, TimeSpan initialDelay, TimeSpan interval) { - StartTimer(key, msg, interval, initialDelay, true); + StartTimer(key, msg, interval, initialDelay, true, ActorRefs.NoSender); + } + + /// + /// Start a periodic timer that will send to the "Self" actor at + /// a fixed . + /// + /// Each timer has a key and if a new timer with same key is started + /// the previous is cancelled and it's guaranteed that a message from the + /// previous timer is not received, even though it might already be enqueued + /// in the mailbox when the new timer is started. + /// + /// Name of timer + /// Message to schedule + /// Initial delay + /// Interval + /// The sender override for the timer message + public void StartPeriodicTimer(object key, object msg, TimeSpan initialDelay, TimeSpan interval, IActorRef sender) + { + StartTimer(key, msg, interval, initialDelay, true, sender); } /// @@ -140,7 +177,25 @@ public void StartPeriodicTimer(object key, object msg, TimeSpan initialDelay, Ti /// Interval public void StartSingleTimer(object key, object msg, TimeSpan timeout) { - StartTimer(key, msg, timeout, TimeSpan.Zero, false); + StartTimer(key, msg, timeout, TimeSpan.Zero, false, ActorRefs.NoSender); + } + + /// + /// Start a timer that will send once to the "Self" actor after + /// the given . + /// + /// Each timer has a key and if a new timer with same key is started + /// the previous is cancelled and it's guaranteed that a message from the + /// previous timer is not received, even though it might already be enqueued + /// in the mailbox when the new timer is started. + /// + /// Name of timer + /// Message to schedule + /// Interval + /// The sender override for the timer message + public void StartSingleTimer(object key, object msg, TimeSpan timeout, IActorRef sender) + { + StartTimer(key, msg, timeout, TimeSpan.Zero, false, sender); } /// @@ -195,7 +250,7 @@ private void CancelTimer(Timer timer) } - private void StartTimer(object key, object msg, TimeSpan timeout, TimeSpan initialDelay, bool repeat) + private void StartTimer(object key, object msg, TimeSpan timeout, TimeSpan initialDelay, bool repeat, IActorRef sender) { if (_timers.TryGetValue(key, out var timer)) CancelTimer(timer); @@ -210,9 +265,9 @@ private void StartTimer(object key, object msg, TimeSpan timeout, TimeSpan initi ICancelable task; if (repeat) - task = _ctx.System.Scheduler.ScheduleTellRepeatedlyCancelable(initialDelay, timeout, _ctx.Self, timerMsg, ActorRefs.NoSender); + task = _ctx.System.Scheduler.ScheduleTellRepeatedlyCancelable(initialDelay, timeout, _ctx.Self, timerMsg, sender); else - task = _ctx.System.Scheduler.ScheduleTellOnceCancelable(timeout, _ctx.Self, timerMsg, ActorRefs.NoSender); + task = _ctx.System.Scheduler.ScheduleTellOnceCancelable(timeout, _ctx.Self, timerMsg, sender); var nextTimer = new Timer(key, msg, repeat, nextGen, task);