Skip to content

Commit afc88cb

Browse files
authored
feat: Allow actors to be configurable (#346)
* WIP actor configurability Signed-off-by: Shubham Sharma <[email protected]> * Refactor config types Signed-off-by: Shubham Sharma <[email protected]> * Use new runtime configuration Signed-off-by: Shubham Sharma <[email protected]> * Remove dependency from Temporal and add unit test Signed-off-by: Shubham Sharma <[email protected]> * Remove commented code Signed-off-by: Shubham Sharma <[email protected]> * Fix lint Signed-off-by: Shubham Sharma <[email protected]> * Refactor Signed-off-by: Shubham Sharma <[email protected]> * Fix actor tests Signed-off-by: Shubham Sharma <[email protected]> * Lint Signed-off-by: Shubham Sharma <[email protected]> * Add e2e test Signed-off-by: Shubham Sharma <[email protected]> * Add docs Signed-off-by: Shubham Sharma <[email protected]> * Simplify response building Signed-off-by: Shubham Sharma <[email protected]> * Add link to time.ParseDuration Signed-off-by: Shubham Sharma <[email protected]> Signed-off-by: Shubham Sharma <[email protected]>
1 parent 22fa407 commit afc88cb

File tree

12 files changed

+314
-159
lines changed

12 files changed

+314
-159
lines changed

daprdocs/content/en/js-sdk-docs/js-actors/_index.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,38 @@ export default class ParkingSensorImpl extends AbstractActor implements ParkingS
6464
}
6565
```
6666

67+
### Configuring Actor Runtime
68+
69+
To configure actor runtime, use the `DaprClientOptions`. The various parameters and their default values are documented at [How-to: Use virtual actors in Dapr](https://docs.dapr.io/developing-applications/building-blocks/actors/howto-actors/#configuration-parameters).
70+
71+
Note, the timeouts and intervals should be formatted as [time.ParseDuration](https://pkg.go.dev/time#ParseDuration) strings.
72+
73+
```javascript
74+
import { CommunicationProtocolEnum, DaprClient, DaprServer } from "@dapr/dapr";
75+
76+
// Configure the actor runtime with the DaprClientOptions.
77+
const clientOptions = {
78+
actor: {
79+
actorIdleTimeout: '1h',
80+
actorScanInterval: '30s',
81+
drainOngoingCallTimeout: '1m',
82+
drainRebalancedActors: true,
83+
reentrancy: {
84+
enabled: true,
85+
maxStackDepth: 32
86+
},
87+
remindersStoragePartitions: 0,
88+
}
89+
}
90+
91+
// Use the options when creating DaprServer and DaprClient.
92+
93+
// Note, DaprServer creates a DaprClient internally, which needs to be configured with clientOptions.
94+
const server = new DaprServer(serverHost, serverPort, daprHost, daprPort, clientOptions);
95+
96+
const client = new DaprClient(daprHost, daprPort, CommunicationProtocolEnum.HTTP, clientOptions);
97+
```
98+
6799
## Registering Actors
68100
Initialize and register your actors by using the `DaprServer` package:
69101

@@ -91,7 +123,7 @@ console.log(`Registered Actors: ${JSON.stringify(resRegisteredActors)}`);
91123
After Actors are registered, create a Proxy object that implements `ParkingSensorInterface` using the `ActorProxyBuilder`. You can invoke the actor methods by directly calling methods on the Proxy object. Internally, it translates to making a network call to the Actor API and fetches the result back.
92124

93125
```javascript
94-
import { DaprClient, ActorId } from "@dapr/dapr";
126+
import { ActorId, DaprClient } from "@dapr/dapr";
95127
import ParkingSensorImpl from "./ParkingSensorImpl";
96128
import ParkingSensorInterface from "./ParkingSensorInterface";
97129

src/actors/runtime/ActorRuntime.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ limitations under the License.
1313

1414
import { DaprClient } from "../..";
1515
import IClient from "../../interfaces/Client/IClient";
16+
import { ActorRuntimeOptions } from "../../types/actors/ActorRuntimeOptions";
1617
import Class from "../../types/Class";
1718
import ActorId from "../ActorId";
1819
import AbstractActor from "./AbstractActor";
1920
import ActorManager from "./ActorManager";
20-
import ActorRuntimeConfig from "./ActorRuntimeConfig";
2121

2222
/**
2323
* Creates instances of "Actor" and activates and deactivates "Actor"
@@ -27,7 +27,6 @@ export default class ActorRuntime {
2727

2828
private readonly daprClient: DaprClient;
2929
private actorManagers: Map<string, ActorManager<any>>;
30-
private actorRuntimeConfig: ActorRuntimeConfig = new ActorRuntimeConfig();
3130

3231
// @todo: we need to make sure race condition cannot happen when accessing the active actors
3332
// NodeJS has an event loop (main thread -> runs JS code) and a worker pool (threadpool -> automatically created for offloading work through libuv) threads
@@ -73,12 +72,12 @@ export default class ActorRuntime {
7372
return Array.from(this.actorManagers.keys());
7473
}
7574

76-
getActorRuntimeConfig(): ActorRuntimeConfig {
77-
return this.actorRuntimeConfig;
75+
getActorRuntimeOptions(): ActorRuntimeOptions {
76+
return this.daprClient.options.actor ?? {};
7877
}
7978

80-
setActorRuntimeConfig(config: ActorRuntimeConfig): void {
81-
this.actorRuntimeConfig = config;
79+
setActorRuntimeOptions(options: ActorRuntimeOptions): void {
80+
this.daprClient.options.actor = options;
8281
}
8382

8483
clearActorManagers(): void {

src/actors/runtime/ActorRuntimeConfig.ts

Lines changed: 0 additions & 77 deletions
This file was deleted.

src/implementation/Server/HTTPServer/actor.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ import Class from '../../../types/Class';
1818
import ActorRuntime from '../../../actors/runtime/ActorRuntime';
1919
import IRequest from '../../../types/http/IRequest';
2020
import IResponse from '../../../types/http/IResponse';
21-
import { GetRegisteredActorsType } from '../../../types/response/GetRegisteredActors.type';
2221
import BufferSerializer from '../../../actors/runtime/BufferSerializer';
2322
import { DaprClient } from '../../..';
2423
import { Logger } from '../../../logger/Logger';
24+
import { getRegisteredActorResponse } from '../../../utils/Actors.util';
2525

2626
// https://docs.dapr.io/reference/api/bindings_api/
2727
export default class HTTPServerActor implements IServerActor {
@@ -70,19 +70,15 @@ export default class HTTPServerActor implements IServerActor {
7070
this.server.getServer().put("/actors/:actorTypeName/:actorId/method/remind/:reminderName", this.handlerReminder.bind(this));
7171
}
7272

73-
private async handlerHealth(req: IRequest, res: IResponse): Promise<void> {
73+
private async handlerHealth(_req: IRequest, res: IResponse): Promise<void> {
7474
return res.send("ok");
7575
}
7676

77-
private async handlerConfig(req: IRequest, res: IResponse): Promise<void> {
77+
private async handlerConfig(_req: IRequest, res: IResponse): Promise<void> {
7878
const actorRuntime = ActorRuntime.getInstance(this.client.getDaprClient());
79-
80-
const result: GetRegisteredActorsType = {
81-
entities: actorRuntime.getRegisteredActorTypes(),
82-
...actorRuntime.getActorRuntimeConfig().toDictionary()
83-
}
84-
85-
return res.send(result);
79+
return res.send(getRegisteredActorResponse(
80+
actorRuntime.getRegisteredActorTypes(),
81+
actorRuntime.getActorRuntimeOptions()));
8682
}
8783

8884
private async handlerDeactivate(req: IRequest, res: IResponse): Promise<void> {

src/types/DaprClientOptions.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ See the License for the specific language governing permissions and
1111
limitations under the License.
1212
*/
1313

14+
import { ActorRuntimeOptions } from "./actors/ActorRuntimeOptions";
1415
import { LoggerOptions } from "./logger/LoggerOptions";
1516

1617
export type DaprClientOptions = {
@@ -24,4 +25,9 @@ export type DaprClientOptions = {
2425
* Options related to logging.
2526
*/
2627
logger?: LoggerOptions;
28+
29+
/**
30+
* Options related to actors.
31+
*/
32+
actor?: ActorRuntimeOptions;
2733
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Copyright 2022 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+
/**
15+
* ActorReentrancyOptions provides options for configuring reentrancy in actors.
16+
* For more, see https://docs.dapr.io/developing-applications/building-blocks/actors/actor-reentrancy/.
17+
*/
18+
export type ActorReentrancyOptions = {
19+
/**
20+
* Configure the reentrancy behavior for an actor. If not provided, reentrancy is disabled.
21+
*/
22+
enabled?: boolean;
23+
24+
/**
25+
* If reentrancy is enabled, this specifies the limit after which concurrent reentrant
26+
* requests to an actor are stopped. This is a safety measure against infinite reentrant calls.
27+
*/
28+
maxStackDepth?: number;
29+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
Copyright 2022 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 { ActorReentrancyOptions } from "./ActorReentrancyOptions";
15+
16+
/**
17+
* ActorRuntimeOptions provides options for configuring the actor runtime in Dapr.
18+
* For more, see https://docs.dapr.io/developing-applications/building-blocks/actors/howto-actors/.
19+
*/
20+
export type ActorRuntimeOptions = {
21+
/**
22+
* The timeout before deactivating an idle actor.
23+
* Checks for timeouts occur every `actorScanInterval` interval.
24+
* It uses the format required by [time.ParseDuration](https://pkg.go.dev/time#ParseDuration).
25+
*/
26+
actorIdleTimeout?: string;
27+
28+
/**
29+
* Specifies how often to scan for idle actors to deactivate them.
30+
* Actors that have been idle longer than `actorIdleTimeout` will be deactivated.
31+
* It uses the format required by [time.ParseDuration](https://pkg.go.dev/time#ParseDuration).
32+
*/
33+
actorScanInterval?: string;
34+
35+
/**
36+
* The timeout before draining current active actor methods.
37+
* If there is no current actor method call, this is ignored.
38+
* It uses the format required by [time.ParseDuration](https://pkg.go.dev/time#ParseDuration).
39+
*/
40+
drainOngoingCallTimeout?: string;
41+
42+
/**
43+
* If true, Dapr will wait for `drainOngoingCallTimeout` before
44+
* draining current active actor methods.
45+
*/
46+
drainRebalancedActors?: boolean;
47+
48+
/**
49+
* Configures different reentrancy parameters.
50+
*/
51+
reentrancy?: ActorReentrancyOptions;
52+
53+
/**
54+
* Specifies the number of partitions for actor’s reminders.
55+
* If not provided, all reminders are saved as a single record in actor’s state store.
56+
*/
57+
remindersStoragePartitions?: number;
58+
}

src/utils/Actors.util.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
Copyright 2022 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 { ActorRuntimeOptions } from "../types/actors/ActorRuntimeOptions";
15+
import { KeyValueType } from "../types/KeyValue.type";
16+
17+
/**
18+
* Get response object for /dapr/config API call.
19+
* See https://docs.dapr.io/reference/api/actors_api/#get-registered-actors
20+
*/
21+
export function getRegisteredActorResponse(entities: string[], options: ActorRuntimeOptions): KeyValueType {
22+
return {
23+
"entities": entities,
24+
...options
25+
}
26+
}

0 commit comments

Comments
 (0)