Skip to content

Commit 0fb83c1

Browse files
authored
Fix actor reminder and timer period parameter (#536)
* Update ActorClientHTTP.ts Signed-off-by: heunghingwan <[email protected]> * Add actor reminder e2e test Signed-off-by: heunghingwan <[email protected]> * Add actor timer e2e test Signed-off-by: heunghingwan <[email protected]> --------- Signed-off-by: heunghingwan <[email protected]>
1 parent 4240c34 commit 0fb83c1

File tree

4 files changed

+156
-2
lines changed

4 files changed

+156
-2
lines changed

src/actors/client/ActorClient/ActorClientHTTP.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export default class ActorClientHTTP implements IClientActor {
6363
"Content-Type": "application/json",
6464
},
6565
body: {
66-
period: reminder.period.toString().toLocaleLowerCase().replace("pt", ""),
66+
period: reminder?.period?.toString()?.toLocaleLowerCase().replace("pt", ""),
6767
dueTime: reminder?.dueTime?.toString()?.toLocaleLowerCase().replace("pt", ""),
6868
ttl: reminder?.ttl?.toString()?.toLocaleLowerCase().replace("pt", ""),
6969
data: reminder.data,
@@ -89,7 +89,7 @@ export default class ActorClientHTTP implements IClientActor {
8989
"Content-Type": "application/json",
9090
},
9191
body: {
92-
period: timer.period.toString().toLocaleLowerCase().replace("pt", ""),
92+
period: timer?.period?.toString()?.toLocaleLowerCase().replace("pt", ""),
9393
dueTime: timer?.dueTime?.toString()?.toLocaleLowerCase().replace("pt", ""),
9494
ttl: timer?.ttl?.toString()?.toLocaleLowerCase().replace("pt", ""),
9595
data: timer.data,
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
Copyright 2023 The Dapr Authors
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
import { AbstractActor, Temporal } from "../../src";
15+
import DemoActorReminderInterface from "./DemoActorReminderInterface";
16+
17+
export default class DemoActorReminderOnceImpl extends AbstractActor implements DemoActorReminderInterface {
18+
counter = 0;
19+
20+
async init(): Promise<string> {
21+
await super.registerActorReminder(
22+
"my-reminder-name",
23+
Temporal.Duration.from({ milliseconds: 1500 }),
24+
undefined,
25+
undefined,
26+
100,
27+
);
28+
29+
return "Actor Initialized";
30+
}
31+
32+
async count(): Promise<void> {
33+
this.counter++;
34+
}
35+
36+
async getCounter(): Promise<number> {
37+
return this.counter;
38+
}
39+
40+
async removeReminder(): Promise<void> {
41+
return this.unregisterActorReminder("my-reminder-name");
42+
}
43+
44+
/**
45+
* @override
46+
* @param data
47+
*/
48+
async receiveReminder(data: string): Promise<void> {
49+
this.counter += parseInt(data);
50+
}
51+
}

test/actor/DemoActorTimerOnceImpl.ts

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
Copyright 2023 The Dapr Authors
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
import { AbstractActor, Temporal } from "../../src";
15+
import DemoActorTimerInterface from "./DemoActorTimerInterface";
16+
17+
export default class DemoActorTimerOnceImpl extends AbstractActor implements DemoActorTimerInterface {
18+
counter = 0;
19+
20+
async init(): Promise<string> {
21+
await super.registerActorTimer(
22+
"my-timer-name",
23+
"countBy",
24+
Temporal.Duration.from({ seconds: 2 }),
25+
undefined,
26+
undefined,
27+
100,
28+
);
29+
return "Actor Initialized";
30+
}
31+
32+
async count(): Promise<void> {
33+
this.counter++;
34+
}
35+
36+
async getCounter(): Promise<number> {
37+
return this.counter;
38+
}
39+
40+
async countBy(amount: string): Promise<void> {
41+
this.counter += parseInt(amount);
42+
}
43+
44+
async removeTimer(): Promise<void> {
45+
return await this.unregisterActorTimer("my-timer-name");
46+
}
47+
}

test/e2e/http/actors.test.ts

+56
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ import DemoActorCounterImpl from "../../actor/DemoActorCounterImpl";
2222
import DemoActorCounterInterface from "../../actor/DemoActorCounterInterface";
2323
import DemoActorReminderImpl from "../../actor/DemoActorReminderImpl";
2424
import DemoActorReminder2Impl from "../../actor/DemoActorReminder2Impl";
25+
import DemoActorReminderOnceImpl from "../../actor/DemoActorReminderOnceImpl";
2526
import DemoActorReminderInterface from "../../actor/DemoActorReminderInterface";
2627
import DemoActorSayImpl from "../../actor/DemoActorSayImpl";
2728
import DemoActorSayInterface from "../../actor/DemoActorSayInterface";
2829
import DemoActorTimerImpl from "../../actor/DemoActorTimerImpl";
30+
import DemoActorTimerOnceImpl from "../../actor/DemoActorTimerOnceImpl";
2931
import DemoActorTimerInterface from "../../actor/DemoActorTimerInterface";
3032
import DemoActorTimerTtlImpl from "../../actor/DemoActorTimerTtlImpl";
3133
import DemoActorReminderTtlImpl from "../../actor/DemoActorReminderTtlImpl";
@@ -82,7 +84,9 @@ describe("http/actors", () => {
8284
await server.actor.registerActor(DemoActorSayImpl);
8385
await server.actor.registerActor(DemoActorReminderImpl);
8486
await server.actor.registerActor(DemoActorReminder2Impl);
87+
await server.actor.registerActor(DemoActorReminderOnceImpl);
8588
await server.actor.registerActor(DemoActorTimerImpl);
89+
await server.actor.registerActor(DemoActorTimerOnceImpl);
8690
await server.actor.registerActor(DemoActorActivateImpl);
8791
await server.actor.registerActor(DemoActorTimerTtlImpl);
8892
await server.actor.registerActor(DemoActorReminderTtlImpl);
@@ -292,6 +296,32 @@ describe("http/actors", () => {
292296
const res4 = await actor.getCounter();
293297
expect(res4).toEqual(200);
294298
}, 10000);
299+
300+
it("should only fire once when period is not set to a timer", async () => {
301+
const builder = new ActorProxyBuilder<DemoActorTimerInterface>(DemoActorTimerOnceImpl, client);
302+
const actor = builder.build(ActorId.createRandomId());
303+
304+
// Activate our actor
305+
await actor.init();
306+
307+
const res0 = await actor.getCounter();
308+
expect(res0).toEqual(0);
309+
310+
// Now we wait for dueTime (2s)
311+
await new Promise((resolve) => setTimeout(resolve, 2000));
312+
313+
// After that the timer callback will be called
314+
// In our case, the callback increments the count attribute
315+
// the count attribute is +100 due to the passed state
316+
const res1 = await actor.getCounter();
317+
expect(res1).toEqual(100);
318+
319+
await new Promise((resolve) => setTimeout(resolve, 1000));
320+
321+
// Make sure the counter didn't change
322+
const res2 = await actor.getCounter();
323+
expect(res2).toEqual(100);
324+
}, 5000);
295325
});
296326

297327
describe("reminders", () => {
@@ -379,5 +409,31 @@ describe("http/actors", () => {
379409
const res2 = await actor.getCounter();
380410
expect(res2).toEqual(123);
381411
});
412+
413+
it("should only fire once when period is not set to a reminder", async () => {
414+
const builder = new ActorProxyBuilder<DemoActorReminderInterface>(DemoActorReminderOnceImpl, client);
415+
const actor = builder.build(ActorId.createRandomId());
416+
417+
// Activate our actor
418+
// this will initialize the reminder to be called
419+
await actor.init();
420+
421+
const res0 = await actor.getCounter();
422+
expect(res0).toEqual(0);
423+
424+
// Now we wait for dueTime (1.5s)
425+
await NodeJSUtil.sleep(1500);
426+
427+
// After that the reminder callback will be called
428+
// In our case, the callback increments the count attribute
429+
const res1 = await actor.getCounter();
430+
expect(res1).toEqual(100);
431+
432+
await new Promise((resolve) => setTimeout(resolve, 1000));
433+
434+
// Make sure the counter didn't change
435+
const res2 = await actor.getCounter();
436+
expect(res2).toEqual(100);
437+
}, 5000);
382438
});
383439
});

0 commit comments

Comments
 (0)