Skip to content

Commit f44b53c

Browse files
committed
feat: Adds error handling around actor deactivation
Signed-off-by: Jared Prather <[email protected]>
1 parent 76866c8 commit f44b53c

File tree

3 files changed

+39
-17
lines changed

3 files changed

+39
-17
lines changed

src/actors/runtime/ActorManager.ts

+22-13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ limitations under the License.
1212
*/
1313

1414
import DaprClient from "../../implementation/Client/DaprClient";
15+
import { Logger } from "../../logger/Logger";
1516
import Class from "../../types/Class";
1617
import ActorId from "../ActorId";
1718
import AbstractActor from "./AbstractActor";
@@ -23,11 +24,17 @@ import BufferSerializer from "./BufferSerializer";
2324
* The Actor Manager manages actor objects of a specific actor type
2425
*/
2526
const REMINDER_METHOD_NAME = "receiveReminder"; // the callback method name for the reminder
27+
export enum DeactivateResult {
28+
Success,
29+
ActorDoesNotExist,
30+
Error,
31+
}
2632

2733
export default class ActorManager<T extends AbstractActor> {
2834
readonly actorCls: Class<T>;
2935
readonly daprClient: DaprClient;
3036
readonly serializer: BufferSerializer = new BufferSerializer();
37+
readonly logger: Logger;
3138

3239
actors: Map<string, T>;
3340

@@ -39,6 +46,7 @@ export default class ActorManager<T extends AbstractActor> {
3946
this.daprClient = daprClient;
4047
this.actorCls = actorCls;
4148

49+
this.logger = new Logger("Actors", "ActorManager", daprClient.options.logger);
4250
this.actors = new Map<string, T>();
4351

4452
// @todo: we need to make sure race condition cannot happen when accessing the active actors
@@ -71,20 +79,21 @@ export default class ActorManager<T extends AbstractActor> {
7179
this.actors.set(actorId.getId(), actor);
7280
}
7381

74-
async deactivateActor(actorId: ActorId): Promise<void> {
75-
if (!this.actors.has(actorId.getId())) {
76-
throw new Error(
77-
JSON.stringify({
78-
error: "ACTOR_NOT_ACTIVATED",
79-
errorMsg: `The actor ${actorId.getId()} was not activated`,
80-
}),
81-
);
82+
async deactivateActor(actorId: ActorId): Promise<DeactivateResult> {
83+
if (this.actors.has(actorId.getId())) {
84+
try {
85+
const actor = await this.getActiveActor(actorId);
86+
await actor.onDeactivateInternal();
87+
return DeactivateResult.Success;
88+
} catch (error) {
89+
this.logger.error("Error encountered deactivating actor");
90+
}
91+
this.actors.delete(actorId.getId());
92+
} else {
93+
this.logger.warn(`The actor ${actorId.getId()} was not activated`);
94+
return DeactivateResult.ActorDoesNotExist;
8295
}
83-
84-
const actor = await this.getActiveActor(actorId);
85-
await actor.onDeactivateInternal();
86-
87-
this.actors.delete(actorId.getId());
96+
return DeactivateResult.Error;
8897
}
8998

9099
async getActiveActor(actorId: ActorId): Promise<T> {

src/actors/runtime/ActorRuntime.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { ActorRuntimeOptions } from "../../types/actors/ActorRuntimeOptions";
1717
import Class from "../../types/Class";
1818
import ActorId from "../ActorId";
1919
import AbstractActor from "./AbstractActor";
20-
import ActorManager from "./ActorManager";
20+
import ActorManager, { DeactivateResult } from "./ActorManager";
2121

2222
/**
2323
* Creates instances of "Actor" and activates and deactivates "Actor"
@@ -141,7 +141,7 @@ export default class ActorRuntime {
141141
return await manager.fireTimer(actorIdObj, name, requestBody);
142142
}
143143

144-
async deactivate(actorTypeName: string, actorId: string): Promise<void> {
144+
async deactivate(actorTypeName: string, actorId: string): Promise<DeactivateResult> {
145145
const actorIdObj = new ActorId(actorId);
146146
const manager = this.getActorManager(actorTypeName);
147147
return await manager.deactivateActor(actorIdObj);

src/implementation/Server/HTTPServer/actor.ts

+15-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { DaprClient } from "../../..";
2323
import { Logger } from "../../../logger/Logger";
2424
import { getRegisteredActorResponse } from "../../../utils/Actors.util";
2525
import HttpStatusCode from "../../../enum/HttpStatusCode.enum";
26+
import { DeactivateResult } from "../../../actors/runtime/ActorManager";
2627

2728
// https://docs.dapr.io/reference/api/bindings_api/
2829
export default class HTTPServerActor implements IServerActor {
@@ -89,8 +90,20 @@ export default class HTTPServerActor implements IServerActor {
8990
private async handlerDeactivate(req: IRequest, res: IResponse): Promise<IResponse> {
9091
const { actorTypeName, actorId } = req.params;
9192
const result = await ActorRuntime.getInstance(this.client.daprClient).deactivate(actorTypeName, actorId);
92-
res.statusCode = HttpStatusCode.OK;
93-
return this.handleResult(res, result);
93+
94+
switch (result) {
95+
case DeactivateResult.Success:
96+
res.statusCode = HttpStatusCode.OK;
97+
return this.handleResult(res, result);
98+
case DeactivateResult.Error:
99+
res.statusCode = HttpStatusCode.INTERNAL_SERVER_ERROR;
100+
return this.handleResult(res, result);
101+
case DeactivateResult.ActorDoesNotExist:
102+
res.statusCode = HttpStatusCode.NOT_FOUND;
103+
return this.handleResult(res, result);
104+
default:
105+
throw new Error("Unsupported result type received");
106+
}
94107
}
95108

96109
private async handlerMethod(req: IRequest, res: IResponse): Promise<IResponse> {

0 commit comments

Comments
 (0)