From 651d4a06d7db0d4b0c9f1c9dd08beec092bec4f5 Mon Sep 17 00:00:00 2001 From: Amulya Varote Date: Mon, 14 Mar 2022 12:38:51 -0700 Subject: [PATCH 1/9] Added ttl param to actor timer and reminder Signed-off-by: Amulya Varote Signed-off-by: Amulya Varote --- daprdocs/content/en/js-sdk-docs/js-actors/_index.md | 4 +++- src/actors/client/ActorClient/ActorClientGRPC.ts | 8 ++++++++ src/actors/client/ActorClient/ActorClientHTTP.ts | 2 ++ src/actors/runtime/AbstractActor.ts | 7 +++++-- src/actors/runtime/ActorReminderData.ts | 13 +++++++++++-- src/types/ActorReminder.type.ts | 1 + src/types/ActorTimer.type.ts | 1 + test/actor/DemoActorReminder2Impl.ts | 2 +- test/actor/DemoActorReminderImpl.ts | 2 +- test/actor/DemoActorTimerImpl.ts | 2 +- test/e2e/actors.http.test.ts | 3 +++ 11 files changed, 37 insertions(+), 8 deletions(-) diff --git a/daprdocs/content/en/js-sdk-docs/js-actors/_index.md b/daprdocs/content/en/js-sdk-docs/js-actors/_index.md index 16740714..736e8a5a 100644 --- a/daprdocs/content/en/js-sdk-docs/js-actors/_index.md +++ b/daprdocs/content/en/js-sdk-docs/js-actors/_index.md @@ -158,7 +158,8 @@ async function start() await client.actor.timerCreate(ParkingSensorImpl.name, `actor-id`, `timer-id`, { callback: "method-to-excute-on-actor", dueTime: Temporal.Duration.from({ seconds: 2 }), - period: Temporal.Duration.from({ seconds: 1 }) + period: Temporal.Duration.from({ seconds: 1 }), + ttl?: Temporal.Duration.from({ seconds: 1 }), }); // Delete the timer @@ -184,6 +185,7 @@ async function start() await client.actor.reminderCreate(DemoActorImpl.name, `actor-id`, `timer-id`, { dueTime: Temporal.Duration.from({ seconds: 2 }), period: Temporal.Duration.from({ seconds: 1 }), + ttl?: Temporal.Duration.from({ seconds: 1 }), data: 100 }); diff --git a/src/actors/client/ActorClient/ActorClientGRPC.ts b/src/actors/client/ActorClient/ActorClientGRPC.ts index 71db5d72..1919bf85 100644 --- a/src/actors/client/ActorClient/ActorClientGRPC.ts +++ b/src/actors/client/ActorClient/ActorClientGRPC.ts @@ -137,6 +137,10 @@ export default class ActorClientGRPC implements IClientActor { msgService.setDueTime(reminder.dueTime.toString()); } + if (reminder.TTL) { + msgService.setTtl(reminder.TTL.toString()); + } + return new Promise((resolve, reject) => { const client = this.client.getClient(); client.registerActorReminder(msgService, (err, _res) => { @@ -191,6 +195,10 @@ export default class ActorClientGRPC implements IClientActor { msgService.setDueTime(timer.dueTime.toString()); } + if (timer.ttl) { + msgService.setTtl(timer.ttl.toString()); + } + return new Promise((resolve, reject) => { const client = this.client.getClient(); client.registerActorTimer(msgService, (err, _res) => { diff --git a/src/actors/client/ActorClient/ActorClientHTTP.ts b/src/actors/client/ActorClient/ActorClientHTTP.ts index 364b83f6..8015a000 100644 --- a/src/actors/client/ActorClient/ActorClientHTTP.ts +++ b/src/actors/client/ActorClient/ActorClientHTTP.ts @@ -60,6 +60,7 @@ export default class ActorClientHTTP implements IClientActor { body: JSON.stringify({ period: reminder.period.toString().toLocaleLowerCase().replace('pt', ''), dueTime: reminder?.dueTime?.toString()?.toLocaleLowerCase().replace('pt', ''), + ttl: reminder?.ttl?.toString()?.toLocaleLowerCase().replace('pt', ''), data: reminder.data }), }); @@ -85,6 +86,7 @@ export default class ActorClientHTTP implements IClientActor { body: JSON.stringify({ period: timer.period.toString().toLocaleLowerCase().replace('pt', ''), dueTime: timer?.dueTime?.toString()?.toLocaleLowerCase().replace('pt', ''), + ttl: timer?.ttl?.toString()?.toLocaleLowerCase().replace('pt', ''), data: timer.data, callback: timer.callback }), diff --git a/src/actors/runtime/AbstractActor.ts b/src/actors/runtime/AbstractActor.ts index 8777c748..9b608d52 100644 --- a/src/actors/runtime/AbstractActor.ts +++ b/src/actors/runtime/AbstractActor.ts @@ -80,14 +80,16 @@ export default abstract class AbstractActor { * @param reminderName name of the reminder * @param state the state to be send along with the reminder trigger * @param dueTime due time for the first trigger + * @param ttl time to live * @param period frequency for the triggers * @param Type of the state object * @return Async void response */ - async registerActorReminder<_Type>(reminderName: string, dueTime: Temporal.Duration, period: Temporal.Duration, state?: any) { + async registerActorReminder<_Type>(reminderName: string, dueTime: Temporal.Duration, ttl: Temporal.Duration, period: Temporal.Duration, state?: any) { await this.actorClient.actor.registerActorReminder(this.actorType, this.id, reminderName, { period, dueTime, + ttl, data: state }); } @@ -96,11 +98,12 @@ export default abstract class AbstractActor { await this.actorClient.actor.unregisterActorReminder(this.actorType, this.id, reminderName); } - async registerActorTimer(timerName: string, callback: string, dueTime: Temporal.Duration, period: Temporal.Duration, state?: any) { + async registerActorTimer(timerName: string, callback: string, dueTime: Temporal.Duration, ttl: Temporal.Duration, period: Temporal.Duration, state?: any) { // Register the timer in the sidecar return await this.actorClient.actor.registerActorTimer(this.actorType, this.id, timerName, { period, dueTime, + ttl, data: state, callback }); diff --git a/src/actors/runtime/ActorReminderData.ts b/src/actors/runtime/ActorReminderData.ts index 34c773be..611908dc 100644 --- a/src/actors/runtime/ActorReminderData.ts +++ b/src/actors/runtime/ActorReminderData.ts @@ -20,17 +20,20 @@ export default class ActorReminderData { readonly reminderName: string; readonly state: string | object | undefined; readonly dueTime: number; + readonly ttl: number; readonly period: number; /** * @param reminderName the name of the actor reminder * @param state the state data passed to receiveReminder callback * @param dueTime the amount of time to delay before invoking the reminder for the first time + * @param ttl time to live * @param period the time interval between reminder invocations after the first invocation */ - constructor(reminderName: string, dueTime: number, period: number, state?: string | object) { + constructor(reminderName: string, dueTime: number, ttl: number, period: number, state?: string | object) { this.reminderName = reminderName; this.dueTime = dueTime; + this.ttl = ttl; this.period = period; this.state = state; } @@ -47,6 +50,10 @@ export default class ActorReminderData { return this.dueTime; } + getTtl(): number { + return this.ttl; + } + getPeriod(): number { return this.period; } @@ -58,6 +65,7 @@ export default class ActorReminderData { return { reminderName: this.reminderName, dueTime: this.dueTime, + ttl: this.ttl, period: this.period, data: this.state } @@ -68,10 +76,11 @@ export default class ActorReminderData { const data = obj?.data; const dueTime = obj?.dueTime; + const ttl = obj?.ttl; const period = obj?.period; const deserializedData = serializer.deserialize(data); - return new ActorReminderData(reminderName, dueTime, period, deserializedData); + return new ActorReminderData(reminderName, dueTime, ttl, period, deserializedData); } } \ No newline at end of file diff --git a/src/types/ActorReminder.type.ts b/src/types/ActorReminder.type.ts index 89870b1a..0827f06f 100644 --- a/src/types/ActorReminder.type.ts +++ b/src/types/ActorReminder.type.ts @@ -17,4 +17,5 @@ export type ActorReminderType = { period: Temporal.Duration; // e.g. 0h0m9s0ms dueTime?: Temporal.Duration; // e.g. 1m or 0h0m0s0ms defaults to 0s data?: any; // the data to pass + ttl?: Temporal.Duration; // e.g. 1m } \ No newline at end of file diff --git a/src/types/ActorTimer.type.ts b/src/types/ActorTimer.type.ts index 3d36e1ff..2e615731 100644 --- a/src/types/ActorTimer.type.ts +++ b/src/types/ActorTimer.type.ts @@ -17,5 +17,6 @@ export type ActorTimerType = { period: Temporal.Duration; // e.g. 0h0m9s0ms dueTime?: Temporal.Duration; // e.g. 1m or 0h0m0s0ms defaults to 0s data?: any; // the data to pass + ttl?: Temporal.Duration; // e.g. 1m callback: string; // which method to execute as callback method } \ No newline at end of file diff --git a/test/actor/DemoActorReminder2Impl.ts b/test/actor/DemoActorReminder2Impl.ts index 700cd0b6..24edced0 100644 --- a/test/actor/DemoActorReminder2Impl.ts +++ b/test/actor/DemoActorReminder2Impl.ts @@ -18,7 +18,7 @@ export default class DemoActorReminder2Impl extends AbstractActor implements Dem counter = 0; async init(): Promise { - await super.registerActorReminder("my-reminder-name", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 1 }), 123); + await super.registerActorReminder("my-reminder-name", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 1 }), 123); return "Actor Initialized"; } diff --git a/test/actor/DemoActorReminderImpl.ts b/test/actor/DemoActorReminderImpl.ts index e6b104ed..49f240d1 100644 --- a/test/actor/DemoActorReminderImpl.ts +++ b/test/actor/DemoActorReminderImpl.ts @@ -18,7 +18,7 @@ export default class DemoActorReminderImpl extends AbstractActor implements Demo counter = 0; async init(): Promise { - await super.registerActorReminder("my-reminder-name", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 1 }), 123); + await super.registerActorReminder("my-reminder-name", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 1 }), 123); return "Actor Initialized"; } diff --git a/test/actor/DemoActorTimerImpl.ts b/test/actor/DemoActorTimerImpl.ts index 7d92fbbf..b4e1cfac 100644 --- a/test/actor/DemoActorTimerImpl.ts +++ b/test/actor/DemoActorTimerImpl.ts @@ -18,7 +18,7 @@ export default class DemoActorTimerImpl extends AbstractActor implements DemoAct counter = 0; async init(): Promise { - await super.registerActorTimer("my-timer-name", "countBy", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 1 }), 100); + await super.registerActorTimer("my-timer-name", "countBy", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 1 }), 100); return "Actor Initialized"; } diff --git a/test/e2e/actors.http.test.ts b/test/e2e/actors.http.test.ts index 79811d3c..e550bc78 100644 --- a/test/e2e/actors.http.test.ts +++ b/test/e2e/actors.http.test.ts @@ -148,6 +148,9 @@ describe('http/actors', () => { // Now we wait for dueTime (2s) await (new Promise(resolve => setTimeout(resolve, 2000))); + // Add time to live (2s) + await (new Promise(resolve => setTimeout(resolve, 2000))); + // After that the timer callback will be called // In our case, the callback increments the count attribute // the count attribute is +100 due to the passed state From eb23da9e314f70d08ab9564295806b8e78443040 Mon Sep 17 00:00:00 2001 From: Amulya Varote Date: Mon, 14 Mar 2022 12:46:33 -0700 Subject: [PATCH 2/9] Changed from TTL to ttl Signed-off-by: Amulya Varote Signed-off-by: Amulya Varote --- src/actors/client/ActorClient/ActorClientGRPC.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/actors/client/ActorClient/ActorClientGRPC.ts b/src/actors/client/ActorClient/ActorClientGRPC.ts index 1919bf85..d62437e6 100644 --- a/src/actors/client/ActorClient/ActorClientGRPC.ts +++ b/src/actors/client/ActorClient/ActorClientGRPC.ts @@ -137,8 +137,8 @@ export default class ActorClientGRPC implements IClientActor { msgService.setDueTime(reminder.dueTime.toString()); } - if (reminder.TTL) { - msgService.setTtl(reminder.TTL.toString()); + if (reminder.ttl) { + msgService.setTtl(reminder.ttl.toString()); } return new Promise((resolve, reject) => { From f6b86c44757820b7ff59d5af10e862cd8c906673 Mon Sep 17 00:00:00 2001 From: Amulya Varote Date: Mon, 14 Mar 2022 12:56:05 -0700 Subject: [PATCH 3/9] Fixed test case Signed-off-by: Amulya Varote Signed-off-by: Amulya Varote --- test/e2e/actors.http.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/actors.http.test.ts b/test/e2e/actors.http.test.ts index e550bc78..0e5e50c5 100644 --- a/test/e2e/actors.http.test.ts +++ b/test/e2e/actors.http.test.ts @@ -155,7 +155,7 @@ describe('http/actors', () => { // In our case, the callback increments the count attribute // the count attribute is +100 due to the passed state const res1 = await actor.getCounter(); - expect(res1).toEqual(100); + expect(res1).toEqual(300); // Every 1 second the timer gets called again, so the count attribute should change // we check this twice to ensure correct calling From ec7fab9aa3abf0212b3778059bb91ea2e86683d1 Mon Sep 17 00:00:00 2001 From: Amulya Varote Date: Mon, 14 Mar 2022 14:04:22 -0700 Subject: [PATCH 4/9] Reverted the test file Signed-off-by: Amulya Varote Signed-off-by: Amulya Varote --- test/e2e/actors.http.test.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/e2e/actors.http.test.ts b/test/e2e/actors.http.test.ts index 0e5e50c5..3cc8359e 100644 --- a/test/e2e/actors.http.test.ts +++ b/test/e2e/actors.http.test.ts @@ -148,14 +148,11 @@ describe('http/actors', () => { // Now we wait for dueTime (2s) await (new Promise(resolve => setTimeout(resolve, 2000))); - // Add time to live (2s) - await (new Promise(resolve => setTimeout(resolve, 2000))); - // After that the timer callback will be called // In our case, the callback increments the count attribute // the count attribute is +100 due to the passed state const res1 = await actor.getCounter(); - expect(res1).toEqual(300); + expect(res1).toEqual(100); // Every 1 second the timer gets called again, so the count attribute should change // we check this twice to ensure correct calling @@ -232,4 +229,4 @@ describe('http/actors', () => { await actor.removeReminder(); }); }); -}); \ No newline at end of file +}); From 1a8dff029c5d7cbec84d4b643bc9c49215880a22 Mon Sep 17 00:00:00 2001 From: Amulya Varote Date: Mon, 14 Mar 2022 14:05:19 -0700 Subject: [PATCH 5/9] Removed last line Signed-off-by: Amulya Varote Signed-off-by: Amulya Varote --- test/e2e/actors.http.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/actors.http.test.ts b/test/e2e/actors.http.test.ts index 3cc8359e..79811d3c 100644 --- a/test/e2e/actors.http.test.ts +++ b/test/e2e/actors.http.test.ts @@ -229,4 +229,4 @@ describe('http/actors', () => { await actor.removeReminder(); }); }); -}); +}); \ No newline at end of file From 0bcd2e8e8c640d7077c799ea6f48523fce72efc9 Mon Sep 17 00:00:00 2001 From: Amulya Varote Date: Thu, 17 Mar 2022 12:07:26 -0700 Subject: [PATCH 6/9] Added test cases Signed-off-by: Amulya Varote Signed-off-by: Amulya Varote --- .../en/js-sdk-docs/js-actors/_index.md | 4 +- src/actors/runtime/AbstractActor.ts | 6 +- src/actors/runtime/ActorReminderData.ts | 8 +-- test/actor/DemoActorReminder2Impl.ts | 3 +- test/actor/DemoActorReminderImpl.ts | 3 +- test/actor/DemoActorReminderTtlImpl.ts | 48 +++++++++++++ test/actor/DemoActorTimerImpl.ts | 3 +- test/actor/DemoActorTimerTtlImpl.ts | 44 ++++++++++++ test/e2e/actors.http.test.ts | 69 +++++++++++++++++++ 9 files changed, 176 insertions(+), 12 deletions(-) create mode 100644 test/actor/DemoActorReminderTtlImpl.ts create mode 100644 test/actor/DemoActorTimerTtlImpl.ts diff --git a/daprdocs/content/en/js-sdk-docs/js-actors/_index.md b/daprdocs/content/en/js-sdk-docs/js-actors/_index.md index 736e8a5a..08276cd2 100644 --- a/daprdocs/content/en/js-sdk-docs/js-actors/_index.md +++ b/daprdocs/content/en/js-sdk-docs/js-actors/_index.md @@ -159,7 +159,7 @@ async function start() callback: "method-to-excute-on-actor", dueTime: Temporal.Duration.from({ seconds: 2 }), period: Temporal.Duration.from({ seconds: 1 }), - ttl?: Temporal.Duration.from({ seconds: 1 }), + ttl: Temporal.Duration.from({ seconds: 1 }), }); // Delete the timer @@ -185,7 +185,7 @@ async function start() await client.actor.reminderCreate(DemoActorImpl.name, `actor-id`, `timer-id`, { dueTime: Temporal.Duration.from({ seconds: 2 }), period: Temporal.Duration.from({ seconds: 1 }), - ttl?: Temporal.Duration.from({ seconds: 1 }), + ttl: Temporal.Duration.from({ seconds: 1 }), data: 100 }); diff --git a/src/actors/runtime/AbstractActor.ts b/src/actors/runtime/AbstractActor.ts index 9b608d52..bcafc349 100644 --- a/src/actors/runtime/AbstractActor.ts +++ b/src/actors/runtime/AbstractActor.ts @@ -80,12 +80,12 @@ export default abstract class AbstractActor { * @param reminderName name of the reminder * @param state the state to be send along with the reminder trigger * @param dueTime due time for the first trigger - * @param ttl time to live + * @param ttl time to duration after which the reminder will be expired and deleted * @param period frequency for the triggers * @param Type of the state object * @return Async void response */ - async registerActorReminder<_Type>(reminderName: string, dueTime: Temporal.Duration, ttl: Temporal.Duration, period: Temporal.Duration, state?: any) { + async registerActorReminder<_Type>(reminderName: string, dueTime: Temporal.Duration, period: Temporal.Duration, ttl?: Temporal.Duration, state?: any) { await this.actorClient.actor.registerActorReminder(this.actorType, this.id, reminderName, { period, dueTime, @@ -98,7 +98,7 @@ export default abstract class AbstractActor { await this.actorClient.actor.unregisterActorReminder(this.actorType, this.id, reminderName); } - async registerActorTimer(timerName: string, callback: string, dueTime: Temporal.Duration, ttl: Temporal.Duration, period: Temporal.Duration, state?: any) { + async registerActorTimer(timerName: string, callback: string, dueTime: Temporal.Duration, period: Temporal.Duration, ttl?: Temporal.Duration, state?: any) { // Register the timer in the sidecar return await this.actorClient.actor.registerActorTimer(this.actorType, this.id, timerName, { period, diff --git a/src/actors/runtime/ActorReminderData.ts b/src/actors/runtime/ActorReminderData.ts index 611908dc..ed8e8878 100644 --- a/src/actors/runtime/ActorReminderData.ts +++ b/src/actors/runtime/ActorReminderData.ts @@ -20,17 +20,17 @@ export default class ActorReminderData { readonly reminderName: string; readonly state: string | object | undefined; readonly dueTime: number; - readonly ttl: number; + readonly ttl: number | undefined; readonly period: number; /** * @param reminderName the name of the actor reminder * @param state the state data passed to receiveReminder callback * @param dueTime the amount of time to delay before invoking the reminder for the first time - * @param ttl time to live + * @param ttl time to duration after which the reminder will be expired and deleted * @param period the time interval between reminder invocations after the first invocation */ - constructor(reminderName: string, dueTime: number, ttl: number, period: number, state?: string | object) { + constructor(reminderName: string, dueTime: number, period: number, ttl?: number, state?: string | object) { this.reminderName = reminderName; this.dueTime = dueTime; this.ttl = ttl; @@ -50,7 +50,7 @@ export default class ActorReminderData { return this.dueTime; } - getTtl(): number { + getTtl(): number | undefined { return this.ttl; } diff --git a/test/actor/DemoActorReminder2Impl.ts b/test/actor/DemoActorReminder2Impl.ts index 24edced0..9bb14abc 100644 --- a/test/actor/DemoActorReminder2Impl.ts +++ b/test/actor/DemoActorReminder2Impl.ts @@ -18,7 +18,8 @@ export default class DemoActorReminder2Impl extends AbstractActor implements Dem counter = 0; async init(): Promise { - await super.registerActorReminder("my-reminder-name", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 1 }), 123); + await super.registerActorReminder("my-reminder-name", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 2 }), + Temporal.Duration.from({ seconds: 1 }), 123); return "Actor Initialized"; } diff --git a/test/actor/DemoActorReminderImpl.ts b/test/actor/DemoActorReminderImpl.ts index 49f240d1..9c12610d 100644 --- a/test/actor/DemoActorReminderImpl.ts +++ b/test/actor/DemoActorReminderImpl.ts @@ -18,7 +18,8 @@ export default class DemoActorReminderImpl extends AbstractActor implements Demo counter = 0; async init(): Promise { - await super.registerActorReminder("my-reminder-name", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 1 }), 123); + await super.registerActorReminder("my-reminder-name", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 2 }), + Temporal.Duration.from({ seconds: 1 }), 123); return "Actor Initialized"; } diff --git a/test/actor/DemoActorReminderTtlImpl.ts b/test/actor/DemoActorReminderTtlImpl.ts new file mode 100644 index 00000000..4b6cfd16 --- /dev/null +++ b/test/actor/DemoActorReminderTtlImpl.ts @@ -0,0 +1,48 @@ +/* +Copyright 2022 The Dapr Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { AbstractActor, Temporal } from "../../src"; +import DemoActorReminderInterface from "./DemoActorReminderInterface"; + +export default class DemoActorReminderTtlImpl extends AbstractActor implements DemoActorReminderInterface { + counter = 0; + + async init(): Promise { + await super.registerActorReminder("my-reminder-name", + Temporal.Duration.from({ seconds: 2 }), //dueTime + Temporal.Duration.from({ seconds: 0.5 }), //period + Temporal.Duration.from({ seconds: 0.5 }), //ttl + 123); + return "Actor Initialized"; + } + + async count(): Promise { + this.counter++; + } + + async getCounter(): Promise { + return this.counter; + } + + async removeReminder(): Promise { + return this.unregisterActorReminder("my-reminder-name"); + } + + /** + * @override + * @param data + */ + async receiveReminder(data: string): Promise { + this.counter += parseInt(data); + } +} \ No newline at end of file diff --git a/test/actor/DemoActorTimerImpl.ts b/test/actor/DemoActorTimerImpl.ts index b4e1cfac..502b9db1 100644 --- a/test/actor/DemoActorTimerImpl.ts +++ b/test/actor/DemoActorTimerImpl.ts @@ -18,7 +18,8 @@ export default class DemoActorTimerImpl extends AbstractActor implements DemoAct counter = 0; async init(): Promise { - await super.registerActorTimer("my-timer-name", "countBy", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 1 }), 100); + await super.registerActorTimer("my-timer-name", "countBy", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 1 }), + undefined, 100); return "Actor Initialized"; } diff --git a/test/actor/DemoActorTimerTtlImpl.ts b/test/actor/DemoActorTimerTtlImpl.ts new file mode 100644 index 00000000..adbe38da --- /dev/null +++ b/test/actor/DemoActorTimerTtlImpl.ts @@ -0,0 +1,44 @@ +/* +Copyright 2022 The Dapr Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { AbstractActor, Temporal } from "../../src"; +import DemoActorTimerInterface from "./DemoActorTimerInterface"; + +export default class DemoActorTimerTtlImpl extends AbstractActor implements DemoActorTimerInterface { + counter = 0; + + async init(): Promise { + await super.registerActorTimer("my-timer-name", "countBy", + Temporal.Duration.from({ seconds: 2 }), //dueTime + Temporal.Duration.from({ seconds: 0.5 }), //period + Temporal.Duration.from({ seconds: 0.5 }), //ttl + 100); + return "Actor Initialized"; + } + + async count(): Promise { + this.counter++; + } + + async getCounter(): Promise { + return this.counter; + } + + async countBy(amount: string): Promise { + this.counter += parseInt(amount); + } + + async removeTimer(): Promise { + return await this.unregisterActorTimer("my-timer-name"); + } +} \ No newline at end of file diff --git a/test/e2e/actors.http.test.ts b/test/e2e/actors.http.test.ts index 79811d3c..62b231d9 100644 --- a/test/e2e/actors.http.test.ts +++ b/test/e2e/actors.http.test.ts @@ -26,6 +26,8 @@ import DemoActorSayImpl from '../actor/DemoActorSayImpl'; import DemoActorSayInterface from '../actor/DemoActorSayInterface'; import DemoActorTimerImpl from '../actor/DemoActorTimerImpl'; import DemoActorTimerInterface from '../actor/DemoActorTimerInterface'; +import DemoActorTimerTtlImpl from '../actor/DemoActorTimerTtlImpl'; +import DemoActorReminderTtlImpl from '../actor/DemoActorReminderTtlImpl'; const serverHost = "127.0.0.1"; const serverPort = "50001"; @@ -171,6 +173,42 @@ describe('http/actors', () => { const res4 = await actor.getCounter(); expect(res4).toEqual(300); }, 10000); + + + it('should apply the ttl when it is set (expected execution time > 5s)', async () => { + const builder = new ActorProxyBuilder(DemoActorTimerTtlImpl, client); + const actor = builder.build(ActorId.createRandomId()); + + // Activate our actor + await actor.init(); + + const res0 = await actor.getCounter(); + expect(res0).toEqual(0); + + // Now we wait for dueTime (2s) + await (new Promise(resolve => setTimeout(resolve, 500))); + + // After that the timer callback will be called + // In our case, the callback increments the count attribute + // the count attribute is +100 due to the passed state + const res1 = await actor.getCounter(); + expect(res1).toEqual(100); + + // Every 1 second the timer gets called again, so the count attribute should change + // we check this twice to ensure correct calling + await (new Promise(resolve => setTimeout(resolve, 500))); + const res2 = await actor.getCounter(); + expect(res2).toEqual(200); + + await (new Promise(resolve => setTimeout(resolve, 500))); + try { + const res3 = await actor.getCounter(); + } catch(e) { + //@ts-ignore + console.log(e.message) + } + // expect(res3).toEqual(300); + }, 10000); }); describe('reminders', () => { @@ -228,5 +266,36 @@ describe('http/actors', () => { // Unregister the reminder await actor.removeReminder(); }); + + it('should apply the ttl when it is set to a reminder', async () => { + const builder = new ActorProxyBuilder(DemoActorReminderTtlImpl, client); + const actor = builder.build(ActorId.createRandomId()); + + // Activate our actor + // this will initialize the reminder to be called + await actor.init(); + + const res0 = await actor.getCounter(); + expect(res0).toEqual(0); + + // Now we wait for dueTime (2s) + await NodeJSUtil.sleep(2000); + + // After that the reminder callback will be called + // In our case, the callback increments the count attribute + const res1 = await actor.getCounter(); + expect(res1).toEqual(123); + + await actor.removeReminder(); + + await (new Promise(resolve => setTimeout(resolve, 500))); + try { + const res2 = await actor.getCounter(); + } catch(e) { + //@ts-ignore + console.log(e.message) + } + // expect(res2).toEqual(123); + }); }); }); \ No newline at end of file From e6c86f8f1e42a227e7a6045fa5fd18bd4d5b0d90 Mon Sep 17 00:00:00 2001 From: Amulya Varote Date: Wed, 13 Apr 2022 16:54:38 -0700 Subject: [PATCH 7/9] Modified test cases for actors ttl Signed-off-by: Amulya Varote --- test/actor/DemoActorReminderTtlImpl.ts | 4 ++-- test/actor/DemoActorTimerTtlImpl.ts | 4 ++-- test/e2e/actors.http.test.ts | 31 ++++++++++---------------- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/test/actor/DemoActorReminderTtlImpl.ts b/test/actor/DemoActorReminderTtlImpl.ts index 4b6cfd16..e47b28a3 100644 --- a/test/actor/DemoActorReminderTtlImpl.ts +++ b/test/actor/DemoActorReminderTtlImpl.ts @@ -20,8 +20,8 @@ export default class DemoActorReminderTtlImpl extends AbstractActor implements D async init(): Promise { await super.registerActorReminder("my-reminder-name", Temporal.Duration.from({ seconds: 2 }), //dueTime - Temporal.Duration.from({ seconds: 0.5 }), //period - Temporal.Duration.from({ seconds: 0.5 }), //ttl + Temporal.Duration.from({ seconds: 2 }), //period + Temporal.Duration.from({ seconds: 1 }), //ttl 123); return "Actor Initialized"; } diff --git a/test/actor/DemoActorTimerTtlImpl.ts b/test/actor/DemoActorTimerTtlImpl.ts index adbe38da..752adc35 100644 --- a/test/actor/DemoActorTimerTtlImpl.ts +++ b/test/actor/DemoActorTimerTtlImpl.ts @@ -20,8 +20,8 @@ export default class DemoActorTimerTtlImpl extends AbstractActor implements Demo async init(): Promise { await super.registerActorTimer("my-timer-name", "countBy", Temporal.Duration.from({ seconds: 2 }), //dueTime - Temporal.Duration.from({ seconds: 0.5 }), //period - Temporal.Duration.from({ seconds: 0.5 }), //ttl + Temporal.Duration.from({ seconds: 2 }), //period + Temporal.Duration.from({ seconds: 1 }), //ttl 100); return "Actor Initialized"; } diff --git a/test/e2e/actors.http.test.ts b/test/e2e/actors.http.test.ts index 62b231d9..71ebfa1c 100644 --- a/test/e2e/actors.http.test.ts +++ b/test/e2e/actors.http.test.ts @@ -63,6 +63,8 @@ describe('http/actors', () => { await server.actor.registerActor(DemoActorReminder2Impl); await server.actor.registerActor(DemoActorTimerImpl); await server.actor.registerActor(DemoActorActivateImpl); + await server.actor.registerActor(DemoActorTimerTtlImpl); + await server.actor.registerActor(DemoActorReminderTtlImpl); // Start server await server.start(); // Start the general server, this can take a while @@ -99,13 +101,15 @@ describe('http/actors', () => { it('should register actors correctly', async () => { const actors = await server.actor.getRegisteredActors(); - expect(actors.length).toEqual(6); + expect(actors.length).toEqual(8); expect(actors).toContain(DemoActorCounterImpl.name); expect(actors).toContain(DemoActorSayImpl.name); expect(actors).toContain(DemoActorReminderImpl.name); expect(actors).toContain(DemoActorTimerImpl.name); expect(actors).toContain(DemoActorActivateImpl.name); + expect(actors).toContain(DemoActorTimerTtlImpl.name); + expect(actors).toContain(DemoActorReminderTtlImpl.name); }); it('should be able to invoke an actor through a text message', async () => { @@ -186,7 +190,7 @@ describe('http/actors', () => { expect(res0).toEqual(0); // Now we wait for dueTime (2s) - await (new Promise(resolve => setTimeout(resolve, 500))); + await (new Promise(resolve => setTimeout(resolve, 1000))); // After that the timer callback will be called // In our case, the callback increments the count attribute @@ -196,18 +200,10 @@ describe('http/actors', () => { // Every 1 second the timer gets called again, so the count attribute should change // we check this twice to ensure correct calling - await (new Promise(resolve => setTimeout(resolve, 500))); + await (new Promise(resolve => setTimeout(resolve, 1000))); const res2 = await actor.getCounter(); expect(res2).toEqual(200); - await (new Promise(resolve => setTimeout(resolve, 500))); - try { - const res3 = await actor.getCounter(); - } catch(e) { - //@ts-ignore - console.log(e.message) - } - // expect(res3).toEqual(300); }, 10000); }); @@ -288,14 +284,11 @@ describe('http/actors', () => { await actor.removeReminder(); - await (new Promise(resolve => setTimeout(resolve, 500))); - try { - const res2 = await actor.getCounter(); - } catch(e) { - //@ts-ignore - console.log(e.message) - } - // expect(res2).toEqual(123); + await (new Promise(resolve => setTimeout(resolve, 2000))); + + // Make sure the counter didn't change + const res2 = await actor.getCounter(); + expect(res2).toEqual(123); }); }); }); \ No newline at end of file From a013a6994254a58667c673b5e0ab6741fcea0a58 Mon Sep 17 00:00:00 2001 From: Amulya Varote Date: Wed, 13 Apr 2022 17:07:29 -0700 Subject: [PATCH 8/9] Fixed e2e tests for actor ttl Signed-off-by: Amulya Varote --- test/actor/DemoActorReminderImpl.ts | 2 +- test/e2e/actors.http.test.ts | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/test/actor/DemoActorReminderImpl.ts b/test/actor/DemoActorReminderImpl.ts index 9c12610d..65b22647 100644 --- a/test/actor/DemoActorReminderImpl.ts +++ b/test/actor/DemoActorReminderImpl.ts @@ -19,7 +19,7 @@ export default class DemoActorReminderImpl extends AbstractActor implements Demo async init(): Promise { await super.registerActorReminder("my-reminder-name", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 2 }), - Temporal.Duration.from({ seconds: 1 }), 123); + undefined, 123); return "Actor Initialized"; } diff --git a/test/e2e/actors.http.test.ts b/test/e2e/actors.http.test.ts index 71ebfa1c..eee45820 100644 --- a/test/e2e/actors.http.test.ts +++ b/test/e2e/actors.http.test.ts @@ -190,7 +190,7 @@ describe('http/actors', () => { expect(res0).toEqual(0); // Now we wait for dueTime (2s) - await (new Promise(resolve => setTimeout(resolve, 1000))); + await (new Promise(resolve => setTimeout(resolve, 2000))); // After that the timer callback will be called // In our case, the callback increments the count attribute @@ -198,11 +198,13 @@ describe('http/actors', () => { const res1 = await actor.getCounter(); expect(res1).toEqual(100); - // Every 1 second the timer gets called again, so the count attribute should change - // we check this twice to ensure correct calling + // Stop the timer + await actor.removeTimer(); + + // We then expect the counter to stop increasing await (new Promise(resolve => setTimeout(resolve, 1000))); - const res2 = await actor.getCounter(); - expect(res2).toEqual(200); + const res4 = await actor.getCounter(); + expect(res4).toEqual(100); }, 10000); }); From 3f088977f0b0126acfb3cff425afc3e199b9926b Mon Sep 17 00:00:00 2001 From: Amulya Varote Date: Wed, 13 Apr 2022 17:15:00 -0700 Subject: [PATCH 9/9] Added a few scenarios to the test case Signed-off-by: Amulya Varote --- test/actor/DemoActorReminderImpl.ts | 2 +- test/actor/DemoActorTimerTtlImpl.ts | 2 +- test/e2e/actors.http.test.ts | 11 ++++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/test/actor/DemoActorReminderImpl.ts b/test/actor/DemoActorReminderImpl.ts index 65b22647..0d8d28f4 100644 --- a/test/actor/DemoActorReminderImpl.ts +++ b/test/actor/DemoActorReminderImpl.ts @@ -18,7 +18,7 @@ export default class DemoActorReminderImpl extends AbstractActor implements Demo counter = 0; async init(): Promise { - await super.registerActorReminder("my-reminder-name", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 2 }), + await super.registerActorReminder("my-reminder-name", Temporal.Duration.from({ seconds: 2 }), Temporal.Duration.from({ seconds: 3 }), undefined, 123); return "Actor Initialized"; } diff --git a/test/actor/DemoActorTimerTtlImpl.ts b/test/actor/DemoActorTimerTtlImpl.ts index 752adc35..2889ae3d 100644 --- a/test/actor/DemoActorTimerTtlImpl.ts +++ b/test/actor/DemoActorTimerTtlImpl.ts @@ -21,7 +21,7 @@ export default class DemoActorTimerTtlImpl extends AbstractActor implements Demo await super.registerActorTimer("my-timer-name", "countBy", Temporal.Duration.from({ seconds: 2 }), //dueTime Temporal.Duration.from({ seconds: 2 }), //period - Temporal.Duration.from({ seconds: 1 }), //ttl + Temporal.Duration.from({ seconds: 3 }), //ttl 100); return "Actor Initialized"; } diff --git a/test/e2e/actors.http.test.ts b/test/e2e/actors.http.test.ts index eee45820..e2c35265 100644 --- a/test/e2e/actors.http.test.ts +++ b/test/e2e/actors.http.test.ts @@ -198,13 +198,22 @@ describe('http/actors', () => { const res1 = await actor.getCounter(); expect(res1).toEqual(100); + // Every 1 second the timer gets called again, so the count attribute should change + // we check this twice to ensure correct calling + await (new Promise(resolve => setTimeout(resolve, 1000))); + const res2 = await actor.getCounter(); + expect(res2).toEqual(100); + await (new Promise(resolve => setTimeout(resolve, 1000))); + const res3 = await actor.getCounter(); + expect(res3).toEqual(200); + // Stop the timer await actor.removeTimer(); // We then expect the counter to stop increasing await (new Promise(resolve => setTimeout(resolve, 1000))); const res4 = await actor.getCounter(); - expect(res4).toEqual(100); + expect(res4).toEqual(200); }, 10000); });