Skip to content

Commit 82e37db

Browse files
Abstracted actor client implementation, required for not exposing actor interfacing publically
Signed-off-by: Xavier Geerinck <[email protected]>
1 parent ca748c1 commit 82e37db

File tree

7 files changed

+626
-214
lines changed

7 files changed

+626
-214
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { DaprClient } from '../../..';
2+
import CommunicationProtocolEnum from '../../../enum/CommunicationProtocol.enum';
3+
import GRPCClient from '../../../implementation/Client/GRPCClient/GRPCClient';
4+
import HTTPClient from '../../../implementation/Client/HTTPClient/HTTPClient';
5+
import IClient from '../../../interfaces/Client/IClient';
6+
import IClientActor from '../../../interfaces/Client/IClientActor';
7+
import ActorClientGRPC from './ActorClientGRPC';
8+
import ActorClientHTTP from './ActorClientHTTP';
9+
10+
export default class ActorClient {
11+
readonly daprClient: DaprClient;
12+
readonly actor: IClientActor;
13+
14+
constructor(daprClient: DaprClient) {
15+
this.daprClient = daprClient;
16+
17+
// Builder
18+
switch (daprClient.communicationProtocol) {
19+
case CommunicationProtocolEnum.GRPC: {
20+
const client = new GRPCClient(this.daprClient.daprHost, this.daprClient.daprPort);
21+
this.actor = new ActorClientGRPC(client);
22+
break;
23+
}
24+
case CommunicationProtocolEnum.HTTP:
25+
default: {
26+
const client = new HTTPClient(this.daprClient.daprHost, this.daprClient.daprPort);
27+
this.actor = new ActorClientHTTP(client);
28+
break;
29+
}
30+
}
31+
}
32+
33+
getDaprClient(): DaprClient {
34+
return this.daprClient;
35+
}
36+
}
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
import { Empty } from "google-protobuf/google/protobuf/empty_pb";
2+
import { Any } from "google-protobuf/google/protobuf/any_pb";
3+
import { ExecuteActorStateTransactionRequest, GetActorStateRequest, GetActorStateResponse, GetMetadataResponse, InvokeActorRequest, InvokeActorResponse, RegisterActorReminderRequest, RegisterActorTimerRequest, TransactionalActorStateOperation, UnregisterActorReminderRequest, UnregisterActorTimerRequest } from '../../../proto/dapr/proto/runtime/v1/dapr_pb';
4+
import GRPCClient from '../../../implementation/Client/GRPCClient/GRPCClient';
5+
import { OperationType } from '../../../types/Operation.type';
6+
import { ActorReminderType } from '../../../types/ActorReminder.type';
7+
import { ActorTimerType } from '../../../types/ActorTimer.type';
8+
import IClientActor from '../../../interfaces/Client/IClientActor';
9+
import { KeyValueType } from '../../../types/KeyValue.type';
10+
11+
// https://docs.dapr.io/reference/api/actors_api/
12+
export default class ActorClientGRPC implements IClientActor {
13+
client: GRPCClient;
14+
15+
constructor(client: GRPCClient) {
16+
this.client = client;
17+
}
18+
19+
async invoke(method: "GET" | "POST" | "PUT" | "DELETE", actorType: string, actorId: string, methodName: string, body?: any): Promise<object> {
20+
const msgService = new InvokeActorRequest();
21+
msgService.setActorId(actorId)
22+
msgService.setActorType(actorType);
23+
msgService.setMethod(methodName);
24+
25+
if (body) {
26+
// @todo: if body is any, do we have to figure out how to serialize in JS? (e.g. if object -> JSON.stringify?)
27+
msgService.setData(body);
28+
}
29+
30+
return new Promise((resolve, reject) => {
31+
const client = this.client.getClient();
32+
client.invokeActor(msgService, (err, res: InvokeActorResponse) => {
33+
if (err) {
34+
return reject(err);
35+
}
36+
37+
// https://docs.dapr.io/reference/api/secrets_api/#response-body
38+
const resData = Buffer.from(res.getData()).toString();
39+
40+
try {
41+
return resolve(JSON.parse(resData));
42+
} catch (e) {
43+
return resolve(resData as any);
44+
}
45+
});
46+
});
47+
}
48+
49+
async stateTransaction(actorType: string, actorId: string, operations: OperationType[]): Promise<void> {
50+
const transactionItems: TransactionalActorStateOperation[] = [];
51+
52+
for (const o of operations) {
53+
const transactionItem = new TransactionalActorStateOperation();
54+
transactionItem.setKey(o.request.key);
55+
transactionItem.setOperationtype(o.operation);
56+
57+
const msgSerialized = new Any();
58+
msgSerialized.setValue(Buffer.from(`${o.request.value}`, "utf-8"));
59+
transactionItem.setValue(msgSerialized);
60+
61+
transactionItems.push(transactionItem);
62+
}
63+
64+
const msgService = new ExecuteActorStateTransactionRequest();
65+
msgService.setActorType(actorType);
66+
msgService.setActorId(actorId);
67+
msgService.setOperationsList(transactionItems);
68+
69+
return new Promise((resolve, reject) => {
70+
const client = this.client.getClient();
71+
client.executeActorStateTransaction(msgService, (err, res) => {
72+
if (err) {
73+
return reject(err);
74+
}
75+
76+
// https://docs.dapr.io/reference/api/state_api/#request-body-1
77+
return resolve();
78+
});
79+
});
80+
}
81+
82+
async stateGet(actorType: string, actorId: string, key: string): Promise<KeyValueType | string> {
83+
const msgService = new GetActorStateRequest();
84+
msgService.setActorType(actorType);
85+
msgService.setActorId(actorId)
86+
msgService.setKey(key);
87+
88+
return new Promise((resolve, reject) => {
89+
const client = this.client.getClient();
90+
client.getActorState(msgService, (err, res: GetActorStateResponse) => {
91+
if (err) {
92+
return reject(err);
93+
}
94+
95+
// https://docs.dapr.io/reference/api/actors_api/#http-response-codes-2
96+
const resData = Buffer.from(res.getData()).toString();
97+
98+
try {
99+
const json = JSON.parse(resData);
100+
return resolve(json);
101+
} catch (e) {
102+
return resolve(resData);
103+
}
104+
});
105+
});
106+
}
107+
108+
async reminderCreate(actorType: string, actorId: string, name: string, reminder: ActorReminderType): Promise<void> {
109+
const msgService = new RegisterActorReminderRequest();
110+
msgService.setActorType(actorType);
111+
msgService.setActorId(actorId);
112+
msgService.setName(name);
113+
114+
if (reminder.data) {
115+
msgService.setData(Buffer.from(reminder?.data.toString(), "utf-8"))
116+
}
117+
118+
if (reminder.period) {
119+
msgService.setPeriod(reminder.period.toString());
120+
}
121+
122+
if (reminder.dueTime) {
123+
msgService.setDueTime(reminder.dueTime.toString());
124+
}
125+
126+
return new Promise((resolve, reject) => {
127+
const client = this.client.getClient();
128+
client.registerActorReminder(msgService, (err, res) => {
129+
if (err) {
130+
return reject(err);
131+
}
132+
133+
// https://docs.dapr.io/reference/api/actors_api/#http-response-codes-3
134+
return resolve();
135+
});
136+
});
137+
}
138+
139+
// @todo: not implemented, cannot find the gRPC bindings
140+
// async reminderGet(actorType: string, actorId: string, name: string): Promise<void> {
141+
// const msgService = new RegisterActorReminderRequest();
142+
// msgService.setActorType(actorType);
143+
// msgService.setActorId(actorId);
144+
// msgService.setName(name);
145+
146+
// if (reminder.data) {
147+
// msgService.setData(Buffer.from(reminder.data, "utf-8"))
148+
// }
149+
150+
// if (reminder.period) {
151+
// msgService.setPeriod(reminder.period);
152+
// }
153+
154+
// if (reminder.dueTime) {
155+
// msgService.setDueTime(reminder.dueTime);
156+
// }
157+
158+
// return new Promise(async (resolve, reject) => {
159+
// const client = await GRPCClientSingleton.getClient();
160+
// client.registerActorReminder(msgService, (err, res) => {
161+
// if (err) {
162+
// return reject(err);
163+
// }
164+
165+
// // https://docs.dapr.io/reference/api/actors_api/#http-response-codes-3
166+
// return resolve();
167+
// });
168+
// });
169+
// }
170+
171+
async reminderDelete(actorType: string, actorId: string, name: string): Promise<void> {
172+
const msgService = new UnregisterActorReminderRequest();
173+
msgService.setActorType(actorType);
174+
msgService.setActorId(actorId);
175+
msgService.setName(name);
176+
177+
return new Promise((resolve, reject) => {
178+
const client = this.client.getClient();
179+
client.unregisterActorReminder(msgService, (err, res) => {
180+
if (err) {
181+
return reject(err);
182+
}
183+
184+
// https://docs.dapr.io/reference/api/actors_api/#delete-actor-reminder
185+
return resolve();
186+
});
187+
});
188+
}
189+
190+
async timerCreate(actorType: string, actorId: string, name: string, timer: ActorTimerType): Promise<void> {
191+
const msgService = new RegisterActorTimerRequest();
192+
msgService.setActorType(actorType);
193+
msgService.setActorId(actorId);
194+
msgService.setName(name);
195+
196+
if (timer.callback) {
197+
msgService.setCallback(timer.callback);
198+
}
199+
200+
if (timer.data) {
201+
msgService.setData(Buffer.from(timer.data, "utf-8"))
202+
}
203+
204+
if (timer.period) {
205+
msgService.setPeriod(timer.period.toString());
206+
}
207+
208+
if (timer.dueTime) {
209+
msgService.setDueTime(timer.dueTime.toString());
210+
}
211+
212+
return new Promise((resolve, reject) => {
213+
const client = this.client.getClient();
214+
client.registerActorTimer(msgService, (err, res) => {
215+
if (err) {
216+
return reject(err);
217+
}
218+
219+
// https://docs.dapr.io/reference/api/actors_api/#http-response-codes-3
220+
return resolve();
221+
});
222+
});
223+
}
224+
225+
async timerDelete(actorType: string, actorId: string, name: string): Promise<void> {
226+
const msgService = new UnregisterActorTimerRequest();
227+
msgService.setActorType(actorType);
228+
msgService.setActorId(actorId);
229+
msgService.setName(name);
230+
231+
return new Promise((resolve, reject) => {
232+
const client = this.client.getClient();
233+
client.unregisterActorTimer(msgService, (err, res) => {
234+
if (err) {
235+
return reject(err);
236+
}
237+
238+
// https://docs.dapr.io/reference/api/actors_api/#delete-actor-timer
239+
return resolve();
240+
});
241+
});
242+
}
243+
244+
// @todo: cannot find this one
245+
// async deactivate(actorType: string, actorId: string): Promise<ResActorDeactivateDto> {
246+
// const msgService = new UnregisterActorTimerRequest();
247+
// msgService.setActorType(actorType);
248+
// msgService.setActorId(actorId);
249+
// msgService.setName(name);
250+
251+
// return new Promise(async (resolve, reject) => {
252+
// const client = await GRPCClientSingleton.getClient();
253+
// client.unregisterActorTimer(msgService, (err, res) => {
254+
// if (err) {
255+
// return reject(err);
256+
// }
257+
258+
// // https://docs.dapr.io/reference/api/actors_api/#delete-actor-timer
259+
// return resolve();
260+
// });
261+
// });
262+
// }
263+
264+
async getActors(): Promise<object> {
265+
return new Promise((resolve, reject) => {
266+
const client = this.client.getClient();
267+
268+
client.getMetadata(new Empty(), (err, res: GetMetadataResponse) => {
269+
if (err) {
270+
return reject(err);
271+
}
272+
273+
// https://docs.dapr.io/reference/api/actors_api/#http-response-codes-2
274+
return resolve(res.getActiveActorsCountList());
275+
});
276+
});
277+
}
278+
}

0 commit comments

Comments
 (0)