Skip to content

Commit 787cba6

Browse files
authored
adding get actor reminder API (#1103)
* get actor reminder API Signed-off-by: Shivam Kumar <[email protected]> * handling serialization better Signed-off-by: Shivam Kumar <[email protected]> --------- Signed-off-by: Shivam Kumar <[email protected]>
1 parent a4f5fc0 commit 787cba6

File tree

15 files changed

+200
-2
lines changed

15 files changed

+200
-2
lines changed

examples/Actor/ActorClient/Program.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ public static async Task Main(string[] args)
9696
receivedData = await proxy.GetData();
9797
Console.WriteLine($"Received data is {receivedData}.");
9898

99+
Console.WriteLine("Getting details of the registered reminder");
100+
var reminder = await proxy.GetReminder();
101+
Console.WriteLine($"Received reminder is {reminder}.");
102+
99103
Console.WriteLine("Deregistering timer. Timers would any way stop if the actor is deactivated as part of Dapr garbage collection.");
100104
await proxy.UnregisterTimer();
101105
Console.WriteLine("Deregistering reminder. Reminders are durable and would not stop until an explicit deregistration or the actor is deleted.");
@@ -105,14 +109,23 @@ public static async Task Main(string[] args)
105109
await proxy.RegisterReminderWithRepetitions(3);
106110
Console.WriteLine("Waiting so the reminder can be triggered");
107111
await Task.Delay(5000);
112+
Console.WriteLine("Getting details of the registered reminder");
113+
reminder = await proxy.GetReminder();
114+
Console.WriteLine($"Received reminder is {reminder}.");
108115
Console.WriteLine("Registering reminder with ttl and repetitions, i.e. reminder stops when either condition is met - The reminder will repeat 2 times.");
109116
await proxy.RegisterReminderWithTtlAndRepetitions(TimeSpan.FromSeconds(5), 2);
117+
Console.WriteLine("Getting details of the registered reminder");
118+
reminder = await proxy.GetReminder();
119+
Console.WriteLine($"Received reminder is {reminder}.");
110120
Console.WriteLine("Deregistering reminder. Reminders are durable and would not stop until an explicit deregistration or the actor is deleted.");
111121
await proxy.UnregisterReminder();
112122

113123
Console.WriteLine("Registering reminder and Timer with TTL - The reminder will self delete after 10 seconds.");
114124
await proxy.RegisterReminderWithTtl(TimeSpan.FromSeconds(10));
115125
await proxy.RegisterTimerWithTtl(TimeSpan.FromSeconds(10));
126+
Console.WriteLine("Getting details of the registered reminder");
127+
reminder = await proxy.GetReminder();
128+
Console.WriteLine($"Received reminder is {reminder}.");
116129

117130
// Track the reminder.
118131
var timer = new Timer(async state => Console.WriteLine($"Received data: {await proxy.GetData()}"), null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));

examples/Actor/DemoActor/DemoActor.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ public async Task RegisterReminderWithTtlAndRepetitions(TimeSpan ttl, int repeti
8585
await this.RegisterReminderAsync("TestReminder", null, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1), repetitions, ttl);
8686
}
8787

88+
public async Task<IActorReminder> GetReminder()
89+
{
90+
return await this.GetReminderAsync("TestReminder");
91+
}
92+
8893
public Task UnregisterReminder()
8994
{
9095
return this.UnregisterReminderAsync("TestReminder");

examples/Actor/IDemoActor/IDemoActor.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace IDemoActorInterface
1616
using System;
1717
using System.Threading.Tasks;
1818
using Dapr.Actors;
19+
using Dapr.Actors.Runtime;
1920

2021
/// <summary>
2122
/// Interface for Actor method.
@@ -94,6 +95,13 @@ public interface IDemoActor : IActor
9495
/// <returns>A task that represents the asynchronous save operation.</returns>
9596
Task RegisterReminderWithTtlAndRepetitions(TimeSpan ttl, int repetitions);
9697

98+
/// <summary>
99+
/// Gets the registered reminder.
100+
/// </summary>
101+
/// <param name="reminderName">The name of the reminder.</param>
102+
/// <returns>A task that returns the reminder after completion.</returns>
103+
Task<IActorReminder> GetReminder();
104+
97105
/// <summary>
98106
/// Unregisters the registered timer.
99107
/// </summary>

src/Dapr.Actors/DaprHttpInteractor.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,23 @@ HttpRequestMessage RequestFunc()
254254
return this.SendAsync(RequestFunc, relativeUrl, cancellationToken);
255255
}
256256

257+
public async Task<Stream> GetReminderAsync(string actorType, string actorId, string reminderName, CancellationToken cancellationToken = default)
258+
{
259+
var relativeUrl = string.Format(CultureInfo.InvariantCulture, Constants.ActorReminderRelativeUrlFormat, actorType, actorId, reminderName);
260+
261+
HttpRequestMessage RequestFunc()
262+
{
263+
var request = new HttpRequestMessage()
264+
{
265+
Method = HttpMethod.Get,
266+
};
267+
return request;
268+
}
269+
270+
var response = await this.SendAsync(RequestFunc, relativeUrl, cancellationToken);
271+
return await response.Content.ReadAsStreamAsync();
272+
}
273+
257274
public Task UnregisterReminderAsync(string actorType, string actorId, string reminderName, CancellationToken cancellationToken = default)
258275
{
259276
var relativeUrl = string.Format(CultureInfo.InvariantCulture, Constants.ActorReminderRelativeUrlFormat, actorType, actorId, reminderName);

src/Dapr.Actors/IDaprInteractor.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,16 @@ internal interface IDaprInteractor
7474
/// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns>
7575
Task RegisterReminderAsync(string actorType, string actorId, string reminderName, string data, CancellationToken cancellationToken = default);
7676

77+
/// <summary>
78+
/// Gets a reminder.
79+
/// </summary>
80+
/// <param name="actorType">Type of actor.</param>
81+
/// <param name="actorId">ActorId.</param>
82+
/// <param name="reminderName">Name of reminder to unregister.</param>
83+
/// <param name="cancellationToken">Cancels the operation.</param>
84+
/// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns>
85+
Task<Stream> GetReminderAsync(string actorType, string actorId, string reminderName, CancellationToken cancellationToken = default);
86+
7787
/// <summary>
7888
/// Unregisters a reminder.
7989
/// </summary>

src/Dapr.Actors/Runtime/Actor.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,18 @@ internal async Task<IActorReminder> RegisterReminderAsync(ActorReminderOptions o
360360
return reminder;
361361
}
362362

363+
/// <summary>
364+
/// Gets a reminder previously registered using <see cref="Dapr.Actors.Runtime.Actor.RegisterReminderAsync(ActorReminderOptions)" />.
365+
/// </summary>
366+
/// <param name="reminderName">The name of the reminder to get.</param>
367+
/// <returns>
368+
/// Returns a task that represents the asynchronous get operation. The result of the task contains the reminder if it exists, otherwise null.
369+
/// </returns>
370+
protected async Task<IActorReminder> GetReminderAsync(string reminderName)
371+
{
372+
return await this.Host.TimerManager.GetReminderAsync(new ActorReminderToken(this.actorTypeName, this.Id, reminderName));
373+
}
374+
363375
/// <summary>
364376
/// Unregisters a reminder previously registered using <see cref="Dapr.Actors.Runtime.Actor.RegisterReminderAsync(ActorReminderOptions)" />.
365377
/// </summary>

src/Dapr.Actors/Runtime/ActorTestOptions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ public override Task RegisterTimerAsync(ActorTimer timer)
9191
throw new NotImplementedException(Message);
9292
}
9393

94+
public override Task<IActorReminder> GetReminderAsync(ActorReminderToken reminder)
95+
{
96+
throw new NotImplementedException(Message);
97+
}
98+
9499
public override Task UnregisterReminderAsync(ActorReminderToken reminder)
95100
{
96101
throw new NotImplementedException(Message);

src/Dapr.Actors/Runtime/ActorTimerManager.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ public abstract class ActorTimerManager
2727
/// <returns>A task which will complete when the operation completes.</returns>
2828
public abstract Task RegisterReminderAsync(ActorReminder reminder);
2929

30+
/// <summary>
31+
/// Gets a reminder previously registered using
32+
/// </summary>
33+
/// <param name="reminder">The <see cref="ActorReminderToken" /> to unregister.</param>
34+
/// <returns>A task which will complete when the operation completes.</returns>
35+
public abstract Task<IActorReminder> GetReminderAsync(ActorReminderToken reminder);
36+
3037
/// <summary>
3138
/// Unregisters the provided reminder with the runtime.
3239
/// </summary>

src/Dapr.Actors/Runtime/DefaultActorTimerManager.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
using System;
1515
using System.Text.Json;
1616
using System.Threading.Tasks;
17+
using System.IO;
18+
using System.Text;
1719

1820
namespace Dapr.Actors.Runtime
1921
{
@@ -37,6 +39,18 @@ public override async Task RegisterReminderAsync(ActorReminder reminder)
3739
await this.interactor.RegisterReminderAsync(reminder.ActorType, reminder.ActorId.ToString(), reminder.Name, serialized);
3840
}
3941

42+
public override async Task<IActorReminder> GetReminderAsync(ActorReminderToken token)
43+
{
44+
if (token == null)
45+
{
46+
throw new ArgumentNullException(nameof(token));
47+
}
48+
49+
var responseStream = await this.interactor.GetReminderAsync(token.ActorType, token.ActorId.ToString(), token.Name);
50+
var reminder = await DeserializeReminderAsync(responseStream, token);
51+
return reminder;
52+
}
53+
4054
public override async Task UnregisterReminderAsync(ActorReminderToken reminder)
4155
{
4256
if (reminder == null)
@@ -77,5 +91,21 @@ private async ValueTask<string> SerializeReminderAsync(ActorReminder reminder)
7791
reminder.Ttl);
7892
return await info.SerializeAsync();
7993
}
94+
95+
private async ValueTask<ActorReminder> DeserializeReminderAsync(Stream stream, ActorReminderToken token)
96+
{
97+
if (stream == null)
98+
{
99+
throw new ArgumentNullException(nameof(stream));
100+
}
101+
var info = await ReminderInfo.DeserializeAsync(stream);
102+
if(info == null)
103+
{
104+
return null;
105+
}
106+
var reminder = new ActorReminder(token.ActorType, token.ActorId, token.Name, info.Data, info.DueTime,
107+
info.Period);
108+
return reminder;
109+
}
80110
}
81111
}

src/Dapr.Actors/Runtime/ReminderInfo.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace Dapr.Actors.Runtime
2020
using System.Threading.Tasks;
2121

2222
// represents the wire format used by Dapr to store reminder info with the runtime
23-
internal struct ReminderInfo
23+
internal class ReminderInfo
2424
{
2525
public ReminderInfo(
2626
byte[] data,
@@ -49,13 +49,16 @@ public ReminderInfo(
4949
internal static async Task<ReminderInfo> DeserializeAsync(Stream stream)
5050
{
5151
var json = await JsonSerializer.DeserializeAsync<JsonElement>(stream);
52+
if(json.ValueKind == JsonValueKind.Null)
53+
{
54+
return null;
55+
}
5256

5357
var dueTime = default(TimeSpan);
5458
var period = default(TimeSpan);
5559
var data = default(byte[]);
5660
int? repetition = null;
5761
TimeSpan? ttl = null;
58-
5962
if (json.TryGetProperty("dueTime", out var dueTimeProperty))
6063
{
6164
var dueTimeString = dueTimeProperty.GetString();

0 commit comments

Comments
 (0)