Skip to content

Commit 0619164

Browse files
Merge branch 'master' into Contributing
2 parents f7f4f59 + d753aae commit 0619164

File tree

12 files changed

+1416
-98
lines changed

12 files changed

+1416
-98
lines changed

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

Lines changed: 92 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -6,116 +6,132 @@ weight: 1000
66
description: How to get up and running with Actors using the Dapr JavaScript SDK
77
---
88

9-
The Dapr actors package allows you to interact with Dapr virtual actors from a JavaScript application. The below examples demonstarte how to use the JavaScript SDK for interacting with virtual actors.
9+
The Dapr actors package allows you to interact with Dapr virtual actors from a JavaScript application. The examples below demonstrate how to use the JavaScript SDK for interacting with virtual actors.
1010

11-
For a more in-depth overview of Dapr actors and supported scenarios, visit the [actors overview page]({{< ref actors-overview >}}).
11+
For a more in-depth overview of Dapr actors, visit the [actors overview page]({{< ref actors-overview >}}).
1212

1313
## Pre-requisites
1414
- [Dapr CLI]({{< ref install-dapr-cli.md >}}) installed
1515
- Initialized [Dapr environment]({{< ref install-dapr-selfhost.md >}})
16-
- [Latest LTS version of Node or greater](https://nodejs.org/en/) d
16+
- [Latest LTS version of Node or greater](https://nodejs.org/en/)
1717
- [JavaScript NPM package installed](https://www.npmjs.com/package/dapr-client)
1818

19+
## Scenario
20+
The below code examples loosely describe the scenario of a Parking Garage Spot Monitoring System, which can be seen in this [video] by Mark Russinovich(https://www.youtube.com/watch?v=eJCu6a-x9uo&t=3785).
21+
22+
A parking garage consists of hundreds of parking spaces, where each parking space includes a sensor that provides updates to a centralized monitoring system. The parking space sensors (our actors) detect if a parking space is occupied, or available.
23+
24+
To jump in and run this example yourself, clone the source code, which can be found in the [JavaScript SDK examples directory](https://github.com/dapr/js-sdk/tree/master/examples/http/actor-parking-sensor).
25+
1926
## Actor Interface
20-
The actor interface defines the contract that is shared between the actor implementation and the clients calling the actor.
27+
The actor interface defines the contract that is shared between the actor implementation and the clients calling the actor. In the example below, we have created an interace for a parking garage sensor. Each sensor has 2 methods: `carEnter` and `carLeave`, which defines the state of the parking space:
2128

2229
```javascript
23-
export default interface ActorSayInterface {
24-
say(msg: string): string;
30+
export default interface ParkingSensorInterface {
31+
carEnter(): Promise<void>;
32+
carLeave(): Promise<void>;
2533
}
2634
```
2735

2836
## Actor Implementation
29-
An actor implementation defines a class by extending the base type `AbstractActor` and implements the interfaces defined in the actor interface.
37+
An actor implementation defines a class by extending the base type `AbstractActor` and implements the actor interface. The following code describes what an actor implmentation consists of by implementing the methods defined in the `ParkingSensorInterface`. It also defines a few extra helper methods:
3038

3139
```javascript
3240
import { AbstractActor } from "dapr-client";
33-
import ActorSayInterface from "./ActorSayInterface";
41+
import ParkingSensorInterface from "./ParkingSensorInterface";
3442

35-
export default class ActorSayImp extends AbstractActor implements ActorSayInterface {
36-
say(msg: string): string {
37-
return `Actor said: "${msg}"`;
38-
}
43+
export default class ParkingSensorImpl extends AbstractActor implements ParkingSensorInterface {
44+
async carEnter(): Promise<void> {
45+
// Implementation that updates state that this parking spaces is occupied.
46+
}
47+
48+
async carLeave(): Promise<void> {
49+
// Implementation that updates state that this parking spaces is available.
50+
}
51+
52+
async getParkingSpaceUpdate(): Promise<object> {
53+
// Implementation of requesting an update from the parking space sensor.
54+
}
55+
56+
async onActivate(): Promise<void> {
57+
// Initialization logic called by AbstractActor.
58+
}
3959
}
4060
```
4161

42-
## Invoking Actors
43-
Use the DaprServer package to create your actors bindings, which will initalize and register your actors. After Actors are registered, use the DaprClient to invoke methods on an actor. The will client call the actor methods defined in the actor interface.
62+
## Registering Actors
63+
Initialize and register your actors by using the DaprServer package:
4464

4565
```javascript
46-
import { DaprServer, DaprClient } from "dapr-client";
47-
import ActorSayImp from "./actor/ActorSayImp";
48-
49-
const daprHost = "127.0.0.1";
50-
const daprPort = "50000"; // Dapr Sidecar Port of this Example Server
51-
const serverHost = "127.0.0.1"; // App Host of this Example Server
52-
const serverPort = "50001"; // App Port of this Example Server
66+
import { DaprServer } from "dapr-server";
67+
import ParkingSensorImpl from "./ParkingSensorImpl";
5368

5469
async function start() {
55-
const server = new DaprServer(serverHost, serverPort, daprHost, daprPort);
56-
const client = new DaprClient(daprHost, daprPort);
70+
const server = new DaprServer(`server-host`, `server-port`, `dapr-host`, `dapr-port`);
71+
72+
await server.actor.init(); // Let the server know we need actors
73+
server.actor.registerActor(ParkingSensorImpl); // Register the actor
74+
await server.startServer(); // Start the server
75+
}
76+
```
5777

58-
// Creating actor bindings
59-
await server.actor.init();
60-
server.actor.registerActor(ActorSayImp);
78+
## Invoking Actors
79+
After Actors are registered, use the DaprClient to invoke methods on an actor. The client will call the actor methods defined in the actor interface.
6180

62-
const actorId = "actor-id";
63-
const timerId = "actor-timer-id";
81+
```javascript
82+
import { DaprClient, DaprServer } from "dapr-client";
83+
import ParkingSensorImpl from "./ParkingSensorImpl";
84+
85+
async function start() {
86+
const server = new DaprServer(`server-host`, `server-port`, `dapr-host`, `dapr-port`);
87+
const client = new DaprClient(`dapr-host`, `dapr-port`);
6488

89+
await server.actor.init();
90+
server.actor.registerActor(ParkingSensorImpl);
6591
await server.startServer();
6692

67-
// Invoke method 'say' with msg 'Hello World'");
68-
const resActorInvokeSay = await client.actor.invoke("PUT", ActorSayImp.name, actorId, "method-to-invoke", "Hello World");
93+
94+
await client.actor.invoke("PUT", ParkingSensorImpl.name, `actor-id`, "carEnter"); // Invoke the ParkingSensor Actor by calling the carEnter function
6995
}
7096
```
7197

7298
## Saving and Getting State
7399

74100
```javascript
75-
import { DaprServer, DaprClient } from "dapr-client";
76-
import StateActor from "./actor/StateActor";
77-
78-
const daprHost = "127.0.0.1";
79-
const daprPort = "50000"; // Dapr Sidecar Port of this Example Server
80-
const serverHost = "127.0.0.1"; // App Host of this Example Server
81-
const serverPort = "50001"; // App Port of this Example Server
101+
import { DaprClient, DaprServer } from "dapr-client";
102+
import ParkingSensorImpl from "./ParkingSensorImpl";
82103

83104
async function start() {
84-
const server = new DaprServer(serverHost, serverPort, daprHost, daprPort);
85-
const client = new DaprClient(daprHost, daprPort);
105+
const server = new DaprServer(`server-host`, `server-port`, `dapr-host`, `dapr-port`);
106+
const client = new DaprClient(`dapr-host`, `dapr-port`);
86107

87-
// Creating actor bindings
88-
await server.actor.init();
89-
server.actor.registerActor(StateActor);
108+
await server.actor.init();
109+
server.actor.registerActor(ParkingSensorImpl);
90110
await server.startServer();
91111

92-
const actorId = "actor-id";
93-
94-
await client.actor.stateTransaction("StateActor", actorId, [
112+
// Perform state transaction
113+
await client.actor.stateTransaction("ParkingSensorImpl", `actor-id`, [
95114
{
96115
operation: "upsert",
97116
request: {
98-
key: "first-key",
99-
value: "hello"
117+
key: "parking-sensor-location-lat",
118+
value: "location-x"
100119
}
101120
},
102121
{
103122
operation: "upsert",
104123
request: {
105-
key: "second-key",
106-
value: "world"
107-
}
108-
},
109-
{
110-
operation: "delete",
111-
request: {
112-
key: "second-key"
124+
key: "parking-sensor-location-lang",
125+
value: "location-y"
113126
}
114127
}
115128
]);
116129

117-
const ActorStateGet = await client.actor.stateGet("StateActor", actorId, "first-key");
130+
// GET state from an actor
131+
await client.actor.stateGet("ParkingSensorImpl", `actor-id`, `parking-sensor-location-lat`)
132+
await client.actor.stateGet("ParkingSensorImpl", `actor-id`, `parking-sensor-location-lang`)
118133
}
134+
...
119135
```
120136

121137
## Actor Timers and Reminders
@@ -127,75 +143,53 @@ The scheduling interface of timers and reminders is identical. For an more in-de
127143

128144
### Actor Timers
129145
```javascript
130-
import { DaprServer, DaprClient } from "dapr-client";
131-
import ActorTimerImpl from "./actor/ActorTimerImpl";
146+
import { DaprClient, DaprServer } from "dapr-client";
147+
import ParkingSensorImpl from "./ParkingSensorImpl";
132148

133-
const daprHost = "127.0.0.1";
134-
const daprPort = "50000"; // Dapr Sidecar Port of this Example Server
135-
const serverHost = "127.0.0.1"; // App Host of this Example Server
136-
const serverPort = "50001"; // App Port of this Example Server
149+
async function start()
150+
const server = new DaprServer(`server-host`, `server-port`, `dapr-host`, `dapr-port`);
151+
const client = new DaprClient(`dapr-host`, `dapr-port`);
137152

138-
async function start() {
139-
const server = new DaprServer(serverHost, serverPort, daprHost, daprPort);
140-
const client = new DaprClient(daprHost, daprPort);
141-
142-
// Creating actor bindings
143-
await server.actor.init();
144-
server.actor.registerActor(ActorTimerImpl);
153+
await server.actor.init();
154+
server.actor.registerActor(ParkingSensorImpl);
145155
await server.startServer();
146156

147-
const actorId = "actor-id";
148-
const timerId = "actor-timer-id";
149-
150-
// Activate actor
151-
await client.actor.invoke("PUT", ActorTimerImpl.name, actorId, "init");
152-
153157
// Register a timer
154-
await client.actor.timerCreate(ActorTimerImpl.name, actorId, timerId, {
155-
callback: "method-to-excute-on-actor",
158+
await client.actor.timerCreate(ParkingSensorImpl.name, `actor-id`, `timer-id`, {
159+
callback: "method-to-excute-on-actor",
156160
dueTime: Temporal.Duration.from({ seconds: 2 }),
157161
period: Temporal.Duration.from({ seconds: 1 })
158162
});
159163

160164
// Delete the timer
161-
await client.actor.timerDelete(ActorTimerImpl.name, actorId, timerId);
165+
await client.actor.timerDelete(ParkingSensorImpl.name, `actor-id`, `timer-id`);
162166
}
163167
```
164168

165169
### Actor Reminders
166170
```javascript
167-
import { DaprServer, DaprClient } from "dapr-client";
168-
import ActorReminderImpl from "./actor/ActorReminderImpl";
171+
import { DaprClient, DaprServer } from "dapr-client";
172+
import ParkingSensorImpl from "./ParkingSensorImpl";
169173

170-
const daprHost = "127.0.0.1";
171-
const daprPort = "50000"; // Dapr Sidecar Port of this Example Server
172-
const serverHost = "127.0.0.1"; // App Host of this Example Server
173-
const serverPort = "50001"; // App Port of this Example Server
174+
async function start()
175+
const server = new DaprServer(`server-host`, `server-port`, `dapr-host`, `dapr-port`);
176+
const client = new DaprClient(`dapr-host`, `dapr-port`);
174177

175-
async function start() {
176-
const server = new DaprServer(serverHost, serverPort, daprHost, daprPort);
177-
const client = new DaprClient(daprHost, daprPort);
178-
179-
// Creating actor bindings
180-
await server.actor.init();
181-
server.actor.registerActor(ActorReminderImpl);
178+
await server.actor.init();
179+
server.actor.registerActor(ParkingSensorImpl);
182180
await server.startServer();
183181

184-
const actorId = "actor-id";
185-
const reminderId = "actor-timer-id";
186-
187-
// Activate our actor
188-
await client.actor.invoke("PUT", ActorReminderImpl.name, actorId, "init");
189182

190183
// Register a reminder, it has a default callback
191-
await client.actor.reminderCreate(ActorReminderImpl.name, actorId, reminderId, {
184+
await client.actor.reminderCreate(DemoActorImpl.name, `actor-id`, `timer-id`, {
192185
dueTime: Temporal.Duration.from({ seconds: 2 }),
193186
period: Temporal.Duration.from({ seconds: 1 }),
194187
data: 100
195188
});
196189

197190
// Delete the reminder
198-
await client.actor.reminderDelete(ActorReminderImpl.name, actorId, reminderId);
191+
await client.actor.reminderDelete(DemoActorImpl.name, `actor-id`, `timer-id`);
192+
}
199193
```
200194

201195
- For a full guide on actors visit [How-To: Use virtual actors in Dapr]({{< ref howto-actors.md >}}).

examples/invocation/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Examples - Invocation
2+
3+
This example demonstrates how to use the Invocation API.
4+
5+
## Run
6+
7+
```bash
8+
# If it is not already, initialize DAPR on the system
9+
dapr init
10+
11+
# Install dependenies
12+
npm install
13+
14+
# Run the example
15+
npm run start:dapr-http
16+
```
17+
18+
## Switching to gRPC
19+
20+
By default the example will run using HTTP. To use gRPC, do the following:
21+
* Replace both occurences of `process.env.DAPR_HTTP_PORT` with `process.env.DAPR_GRPC_PORT`
22+
* Replace both occurences of `CommunicationProtocolEnum.HTTP` with `CommunicationProtocolEnum.GRPC`
23+
* Instead of `npm run start:dapr-http` run `npm run start:dapr-grpc`

0 commit comments

Comments
 (0)