diff --git a/src/Microsoft.Actions.Actors/ActionsHttpInteractor.cs b/src/Microsoft.Actions.Actors/ActionsHttpInteractor.cs
index 15225d73..d631fd98 100644
--- a/src/Microsoft.Actions.Actors/ActionsHttpInteractor.cs
+++ b/src/Microsoft.Actions.Actors/ActionsHttpInteractor.cs
@@ -271,6 +271,44 @@ namespace Microsoft.Actions.Actors
return this.SendAsync(RequestFunc, relativeUrl, requestId, cancellationToken);
}
+ public Task RegisterTimerAsync(string actorType, string actorId, string timerName, string data, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var relativeUrl = string.Format(CultureInfo.InvariantCulture, Constants.ActorTimerRelativeUrlFormat, actorType, actorId, timerName);
+ var requestId = Guid.NewGuid().ToString();
+
+ HttpRequestMessage RequestFunc()
+ {
+ var request = new HttpRequestMessage()
+ {
+ Method = HttpMethod.Put,
+ Content = new StringContent(data, Encoding.UTF8),
+ };
+
+ request.Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json; charset=utf-8");
+ return request;
+ }
+
+ return this.SendAsync(RequestFunc, relativeUrl, requestId, cancellationToken);
+ }
+
+ public Task UnregisterTimerAsync(string actorType, string actorId, string timerName, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var relativeUrl = string.Format(CultureInfo.InvariantCulture, Constants.Timers, actorType, actorId, timerName);
+ var requestId = Guid.NewGuid().ToString();
+
+ HttpRequestMessage RequestFunc()
+ {
+ var request = new HttpRequestMessage()
+ {
+ Method = HttpMethod.Delete,
+ };
+
+ return request;
+ }
+
+ return this.SendAsync(RequestFunc, relativeUrl, requestId, cancellationToken);
+ }
+
///
/// Sends an HTTP get request to Actions.
///
diff --git a/src/Microsoft.Actions.Actors/AspNetCore/ActionsActorSetupFilter.cs b/src/Microsoft.Actions.Actors/AspNetCore/ActionsActorSetupFilter.cs
index 0be5c29d..ea85fed7 100644
--- a/src/Microsoft.Actions.Actors/AspNetCore/ActionsActorSetupFilter.cs
+++ b/src/Microsoft.Actions.Actors/AspNetCore/ActionsActorSetupFilter.cs
@@ -24,6 +24,7 @@ namespace Microsoft.Actions.Actors.AspNetCore
actorRouteBuilder.AddActorDeactivationRoute();
actorRouteBuilder.AddActorMethodRoute();
actorRouteBuilder.AddReminderRoute();
+ actorRouteBuilder.AddTimerRoute();
app.UseRouter(actorRouteBuilder.Build());
next(app);
diff --git a/src/Microsoft.Actions.Actors/AspNetCore/RouterBuilderExtensions.cs b/src/Microsoft.Actions.Actors/AspNetCore/RouterBuilderExtensions.cs
index bd589858..31565d55 100644
--- a/src/Microsoft.Actions.Actors/AspNetCore/RouterBuilderExtensions.cs
+++ b/src/Microsoft.Actions.Actors/AspNetCore/RouterBuilderExtensions.cs
@@ -89,5 +89,18 @@ namespace Microsoft.Actions.Actors.AspNetCore
return ActorRuntime.FireReminderAsync(actorTypeName, actorId, reminderName, request.Body);
});
}
+
+ public static void AddTimerRoute(this IRouteBuilder routeBuilder)
+ {
+ routeBuilder.MapPut("actors/{actorTypeName}/{actorId}/method/timer/{timerName}", (request, response, routeData) =>
+ {
+ var actorTypeName = (string)routeData.Values["actorTypeName"];
+ var actorId = (string)routeData.Values["actorId"];
+ var timerName = (string)routeData.Values["timerName"];
+
+ // read dueTime, period and data from Request Body.
+ return ActorRuntime.FireTimerAsync(actorTypeName, actorId, timerName);
+ });
+ }
}
}
diff --git a/src/Microsoft.Actions.Actors/Constants.cs b/src/Microsoft.Actions.Actors/Constants.cs
index a5646b6c..fdb3e81b 100644
--- a/src/Microsoft.Actions.Actors/Constants.cs
+++ b/src/Microsoft.Actions.Actors/Constants.cs
@@ -24,6 +24,7 @@ namespace Microsoft.Actions.Actors
public const string ActionsVersion = "v1.0";
public const string Method = "method";
public const string Reminders = "reminders";
+ public const string Timers = "timers";
///
/// Gets string format for Actors state management relative url.
@@ -44,5 +45,10 @@ namespace Microsoft.Actions.Actors
/// Gets string format for Actors reminder registration relative url..
///
public static string ActorReminderRelativeUrlFormat => $"{ActionsVersion}/{Actors}/{{0}}/{{1}}/{Reminders}/{{2}}";
+
+ ///
+ /// Gets string format for Actors timer registration relative url..
+ ///
+ public static string ActorTimerRelativeUrlFormat => $"{ActionsVersion}/{Actors}/{{0}}/{{1}}/{Timers}/{{2}}";
}
}
diff --git a/src/Microsoft.Actions.Actors/IActionsInteractor.cs b/src/Microsoft.Actions.Actors/IActionsInteractor.cs
index a38d2a78..5b34fc0f 100644
--- a/src/Microsoft.Actions.Actors/IActionsInteractor.cs
+++ b/src/Microsoft.Actions.Actors/IActionsInteractor.cs
@@ -79,7 +79,7 @@ namespace Microsoft.Actions.Actors
Task InvokeActorMethodWithRemotingAsync(IActorRequestMessage remotingRequestRequestMessage, CancellationToken cancellationToken = default(CancellationToken));
///
- /// Invokes Actor method.
+ /// Register a reminder.
///
/// Type of actor.
/// ActorId.
@@ -90,7 +90,7 @@ namespace Microsoft.Actions.Actors
Task RegisterReminderAsync(string actorType, string actorId, string reminderName, string data, CancellationToken cancellationToken = default(CancellationToken));
///
- /// Invokes Actor method.
+ /// Unregisters a reminder.
///
/// Type of actor.
/// ActorId.
@@ -98,5 +98,26 @@ namespace Microsoft.Actions.Actors
/// Cancels the operation.
/// A representing the result of the asynchronous operation.
Task UnregisterReminderAsync(string actorType, string actorId, string reminderName, CancellationToken cancellationToken = default(CancellationToken));
+
+ ///
+ /// Registers a timer.
+ ///
+ /// Type of actor.
+ /// ActorId.
+ /// Name of timer to register.
+ /// Json reminder data as per the actions spec.
+ /// Cancels the operation.
+ /// A representing the result of the asynchronous operation.
+ Task RegisterTimerAsync(string actorType, string actorId, string timerName, string data, CancellationToken cancellationToken = default(CancellationToken));
+
+ ///
+ /// Unegisters a timer.
+ ///
+ /// Type of actor.
+ /// ActorId.
+ /// Name of timer to register.
+ /// Cancels the operation.
+ /// A representing the result of the asynchronous operation.
+ Task UnregisterTimerAsync(string actorType, string actorId, string timerName, CancellationToken cancellationToken = default(CancellationToken));
}
}
diff --git a/src/Microsoft.Actions.Actors/Runtime/Actor.cs b/src/Microsoft.Actions.Actors/Runtime/Actor.cs
index 6a48f05e..452e781d 100644
--- a/src/Microsoft.Actions.Actors/Runtime/Actor.cs
+++ b/src/Microsoft.Actions.Actors/Runtime/Actor.cs
@@ -6,6 +6,7 @@
namespace Microsoft.Actions.Actors.Runtime
{
using System;
+ using System.Collections.Generic;
using System.Threading.Tasks;
///
@@ -22,6 +23,11 @@ namespace Microsoft.Actions.Actors.Runtime
private readonly string traceId;
private readonly string actorImplementaionTypeName;
+ ///
+ /// Contains timers to be invoked.
+ ///
+ private Dictionary timers = new Dictionary();
+
///
/// Initializes a new instance of the class.
///
@@ -97,6 +103,12 @@ namespace Microsoft.Actions.Actors.Runtime
return this.StateManager.ClearCacheAsync();
}
+ internal Task FireTimerAsync(string timerName)
+ {
+ var timer = this.timers[timerName];
+ return timer.AsyncCallback.Invoke(timer.State);
+ }
+
///
/// Saves all the state changes (add/update/remove) that were made since last call to
/// ,
@@ -201,9 +213,9 @@ namespace Microsoft.Actions.Actors.Runtime
TimeSpan dueTime,
TimeSpan period)
{
- var reminderData = new ReminderData(state, dueTime, period);
- var reminder = new ActorReminder(this.Id, reminderName, reminderData);
- await ActorRuntime.ActionsInteractor.RegisterReminderAsync(this.actorImplementaionTypeName, this.Id.ToString(), reminderName, reminderData.SerializeToJson());
+ var reminderInfo = new ReminderInfo(state, dueTime, period);
+ var reminder = new ActorReminder(this.Id, reminderName, reminderInfo);
+ await ActorRuntime.ActionsInteractor.RegisterReminderAsync(this.actorImplementaionTypeName, this.Id.ToString(), reminderName, reminderInfo.SerializeToJson());
return reminder;
}
@@ -230,5 +242,97 @@ namespace Microsoft.Actions.Actors.Runtime
{
return ActorRuntime.ActionsInteractor.UnregisterReminderAsync(this.actorImplementaionTypeName, this.Id.ToString(), reminderName);
}
+
+ ///
+ /// Registers a Timer for the actor. A timer name is autogenerated by the runtime to keep track of it.
+ ///
+ ///
+ /// A delegate that specifies a method to be called when the timer fires.
+ /// It has one parameter: the state object passed to RegisterTimer.
+ /// It returns a representing the asynchronous operation.
+ ///
+ /// An object containing information to be used by the callback method, or null.
+ /// The amount of time to delay before the async callback is first invoked.
+ /// Specify negative one (-1) milliseconds to prevent the timer from starting.
+ /// Specify zero (0) to start the timer immediately.
+ ///
+ ///
+ /// The time interval between invocations of the async callback.
+ /// Specify negative one (-1) milliseconds to disable periodic signaling.
+ /// Returns IActorTimer object.
+ protected Task RegisterTimerAsync(
+ Func