rivetkit 2.0.2 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/schemas/actor-persist/v1.ts +228 -0
- package/dist/schemas/client-protocol/v1.ts +429 -0
- package/dist/schemas/file-system-driver/v1.ts +102 -0
- package/dist/tsup/actor/errors.cjs +69 -0
- package/dist/tsup/actor/errors.cjs.map +1 -0
- package/dist/tsup/actor/errors.d.cts +143 -0
- package/dist/tsup/actor/errors.d.ts +143 -0
- package/dist/tsup/actor/errors.js +69 -0
- package/dist/tsup/actor/errors.js.map +1 -0
- package/dist/tsup/chunk-2CRLFV6Z.cjs +202 -0
- package/dist/tsup/chunk-2CRLFV6Z.cjs.map +1 -0
- package/dist/tsup/chunk-3H7O2A7I.js +525 -0
- package/dist/tsup/chunk-3H7O2A7I.js.map +1 -0
- package/dist/tsup/chunk-42I3OZ3Q.js +15 -0
- package/dist/tsup/chunk-42I3OZ3Q.js.map +1 -0
- package/dist/tsup/chunk-4NSUQZ2H.js +1790 -0
- package/dist/tsup/chunk-4NSUQZ2H.js.map +1 -0
- package/dist/tsup/chunk-6PDXBYI5.js +132 -0
- package/dist/tsup/chunk-6PDXBYI5.js.map +1 -0
- package/dist/tsup/chunk-6WKQDDUD.cjs +1790 -0
- package/dist/tsup/chunk-6WKQDDUD.cjs.map +1 -0
- package/dist/tsup/chunk-CTBOSFUH.cjs +116 -0
- package/dist/tsup/chunk-CTBOSFUH.cjs.map +1 -0
- package/dist/tsup/chunk-EGVZZFE2.js +2857 -0
- package/dist/tsup/chunk-EGVZZFE2.js.map +1 -0
- package/dist/tsup/chunk-FCCPJNMA.cjs +132 -0
- package/dist/tsup/chunk-FCCPJNMA.cjs.map +1 -0
- package/dist/tsup/chunk-FLMTTN27.js +244 -0
- package/dist/tsup/chunk-FLMTTN27.js.map +1 -0
- package/dist/tsup/chunk-GIR3AFFI.cjs +315 -0
- package/dist/tsup/chunk-GIR3AFFI.cjs.map +1 -0
- package/dist/tsup/chunk-INGJP237.js +315 -0
- package/dist/tsup/chunk-INGJP237.js.map +1 -0
- package/dist/tsup/chunk-KJCJLKRM.js +116 -0
- package/dist/tsup/chunk-KJCJLKRM.js.map +1 -0
- package/dist/tsup/chunk-KUPQZYUQ.cjs +15 -0
- package/dist/tsup/chunk-KUPQZYUQ.cjs.map +1 -0
- package/dist/tsup/chunk-O2MBYIXO.cjs +2857 -0
- package/dist/tsup/chunk-O2MBYIXO.cjs.map +1 -0
- package/dist/tsup/chunk-OGAPU3UG.cjs +525 -0
- package/dist/tsup/chunk-OGAPU3UG.cjs.map +1 -0
- package/dist/tsup/chunk-OV6AYD4S.js +4406 -0
- package/dist/tsup/chunk-OV6AYD4S.js.map +1 -0
- package/dist/tsup/chunk-PO4VLDWA.js +47 -0
- package/dist/tsup/chunk-PO4VLDWA.js.map +1 -0
- package/dist/tsup/chunk-R2OPSKIV.cjs +244 -0
- package/dist/tsup/chunk-R2OPSKIV.cjs.map +1 -0
- package/dist/tsup/chunk-TZJKSBUQ.cjs +47 -0
- package/dist/tsup/chunk-TZJKSBUQ.cjs.map +1 -0
- package/dist/tsup/chunk-UBUC5C3G.cjs +189 -0
- package/dist/tsup/chunk-UBUC5C3G.cjs.map +1 -0
- package/dist/tsup/chunk-UIM22YJL.cjs +4406 -0
- package/dist/tsup/chunk-UIM22YJL.cjs.map +1 -0
- package/dist/tsup/chunk-URVFQMYI.cjs +230 -0
- package/dist/tsup/chunk-URVFQMYI.cjs.map +1 -0
- package/dist/tsup/chunk-UVUPOS46.js +230 -0
- package/dist/tsup/chunk-UVUPOS46.js.map +1 -0
- package/dist/tsup/chunk-VRRHBNJC.js +189 -0
- package/dist/tsup/chunk-VRRHBNJC.js.map +1 -0
- package/dist/tsup/chunk-XFSS33EQ.js +202 -0
- package/dist/tsup/chunk-XFSS33EQ.js.map +1 -0
- package/dist/tsup/client/mod.cjs +32 -0
- package/dist/tsup/client/mod.cjs.map +1 -0
- package/dist/tsup/client/mod.d.cts +26 -0
- package/dist/tsup/client/mod.d.ts +26 -0
- package/dist/tsup/client/mod.js +32 -0
- package/dist/tsup/client/mod.js.map +1 -0
- package/dist/tsup/common/log.cjs +13 -0
- package/dist/tsup/common/log.cjs.map +1 -0
- package/dist/tsup/common/log.d.cts +20 -0
- package/dist/tsup/common/log.d.ts +20 -0
- package/dist/tsup/common/log.js +13 -0
- package/dist/tsup/common/log.js.map +1 -0
- package/dist/tsup/common/websocket.cjs +10 -0
- package/dist/tsup/common/websocket.cjs.map +1 -0
- package/dist/tsup/common/websocket.d.cts +3 -0
- package/dist/tsup/common/websocket.d.ts +3 -0
- package/dist/tsup/common/websocket.js +10 -0
- package/dist/tsup/common/websocket.js.map +1 -0
- package/dist/tsup/common-CpqORuCq.d.cts +218 -0
- package/dist/tsup/common-CpqORuCq.d.ts +218 -0
- package/dist/tsup/connection-BR_Ve4ku.d.cts +2117 -0
- package/dist/tsup/connection-BwUMoe6n.d.ts +2117 -0
- package/dist/tsup/driver-helpers/mod.cjs +33 -0
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -0
- package/dist/tsup/driver-helpers/mod.d.cts +18 -0
- package/dist/tsup/driver-helpers/mod.d.ts +18 -0
- package/dist/tsup/driver-helpers/mod.js +33 -0
- package/dist/tsup/driver-helpers/mod.js.map +1 -0
- package/dist/tsup/driver-test-suite/mod.cjs +4619 -0
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -0
- package/dist/tsup/driver-test-suite/mod.d.cts +57 -0
- package/dist/tsup/driver-test-suite/mod.d.ts +57 -0
- package/dist/tsup/driver-test-suite/mod.js +4619 -0
- package/dist/tsup/driver-test-suite/mod.js.map +1 -0
- package/dist/tsup/inspector/mod.cjs +53 -0
- package/dist/tsup/inspector/mod.cjs.map +1 -0
- package/dist/tsup/inspector/mod.d.cts +408 -0
- package/dist/tsup/inspector/mod.d.ts +408 -0
- package/dist/tsup/inspector/mod.js +53 -0
- package/dist/tsup/inspector/mod.js.map +1 -0
- package/dist/tsup/mod.cjs +73 -0
- package/dist/tsup/mod.cjs.map +1 -0
- package/dist/tsup/mod.d.cts +100 -0
- package/dist/tsup/mod.d.ts +100 -0
- package/dist/tsup/mod.js +73 -0
- package/dist/tsup/mod.js.map +1 -0
- package/dist/tsup/router-endpoints-AYkXG8Tl.d.cts +66 -0
- package/dist/tsup/router-endpoints-DAbqVFx2.d.ts +66 -0
- package/dist/tsup/test/mod.cjs +21 -0
- package/dist/tsup/test/mod.cjs.map +1 -0
- package/dist/tsup/test/mod.d.cts +27 -0
- package/dist/tsup/test/mod.d.ts +27 -0
- package/dist/tsup/test/mod.js +21 -0
- package/dist/tsup/test/mod.js.map +1 -0
- package/dist/tsup/utils-CT0cv4jd.d.cts +17 -0
- package/dist/tsup/utils-CT0cv4jd.d.ts +17 -0
- package/dist/tsup/utils.cjs +26 -0
- package/dist/tsup/utils.cjs.map +1 -0
- package/dist/tsup/utils.d.cts +36 -0
- package/dist/tsup/utils.d.ts +36 -0
- package/dist/tsup/utils.js +26 -0
- package/dist/tsup/utils.js.map +1 -0
- package/package.json +208 -5
- package/src/actor/action.ts +182 -0
- package/src/actor/config.ts +765 -0
- package/src/actor/connection.ts +260 -0
- package/src/actor/context.ts +171 -0
- package/src/actor/database.ts +23 -0
- package/src/actor/definition.ts +86 -0
- package/src/actor/driver.ts +84 -0
- package/src/actor/errors.ts +360 -0
- package/src/actor/generic-conn-driver.ts +234 -0
- package/src/actor/instance.ts +1800 -0
- package/src/actor/log.ts +15 -0
- package/src/actor/mod.ts +113 -0
- package/src/actor/persisted.ts +42 -0
- package/src/actor/protocol/old.ts +281 -0
- package/src/actor/protocol/serde.ts +131 -0
- package/src/actor/router-endpoints.ts +685 -0
- package/src/actor/router.ts +263 -0
- package/src/actor/schedule.ts +17 -0
- package/src/actor/unstable-react.ts +110 -0
- package/src/actor/utils.ts +98 -0
- package/src/client/actor-common.ts +30 -0
- package/src/client/actor-conn.ts +804 -0
- package/src/client/actor-handle.ts +208 -0
- package/src/client/client.ts +623 -0
- package/src/client/errors.ts +41 -0
- package/src/client/http-client-driver.ts +326 -0
- package/src/client/log.ts +7 -0
- package/src/client/mod.ts +56 -0
- package/src/client/raw-utils.ts +92 -0
- package/src/client/test.ts +44 -0
- package/src/client/utils.ts +150 -0
- package/src/common/eventsource-interface.ts +47 -0
- package/src/common/eventsource.ts +80 -0
- package/src/common/fake-event-source.ts +266 -0
- package/src/common/inline-websocket-adapter2.ts +445 -0
- package/src/common/log-levels.ts +27 -0
- package/src/common/log.ts +139 -0
- package/src/common/logfmt.ts +228 -0
- package/src/common/network.ts +2 -0
- package/src/common/router.ts +87 -0
- package/src/common/utils.ts +322 -0
- package/src/common/versioned-data.ts +95 -0
- package/src/common/websocket-interface.ts +49 -0
- package/src/common/websocket.ts +43 -0
- package/src/driver-helpers/mod.ts +22 -0
- package/src/driver-helpers/utils.ts +17 -0
- package/src/driver-test-suite/log.ts +7 -0
- package/src/driver-test-suite/mod.ts +213 -0
- package/src/driver-test-suite/test-inline-client-driver.ts +402 -0
- package/src/driver-test-suite/tests/action-features.ts +136 -0
- package/src/driver-test-suite/tests/actor-auth.ts +591 -0
- package/src/driver-test-suite/tests/actor-conn-state.ts +249 -0
- package/src/driver-test-suite/tests/actor-conn.ts +349 -0
- package/src/driver-test-suite/tests/actor-driver.ts +25 -0
- package/src/driver-test-suite/tests/actor-error-handling.ts +158 -0
- package/src/driver-test-suite/tests/actor-handle.ts +259 -0
- package/src/driver-test-suite/tests/actor-inline-client.ts +152 -0
- package/src/driver-test-suite/tests/actor-inspector.ts +570 -0
- package/src/driver-test-suite/tests/actor-metadata.ts +116 -0
- package/src/driver-test-suite/tests/actor-onstatechange.ts +95 -0
- package/src/driver-test-suite/tests/actor-schedule.ts +108 -0
- package/src/driver-test-suite/tests/actor-sleep.ts +413 -0
- package/src/driver-test-suite/tests/actor-state.ts +54 -0
- package/src/driver-test-suite/tests/actor-vars.ts +93 -0
- package/src/driver-test-suite/tests/manager-driver.ts +365 -0
- package/src/driver-test-suite/tests/raw-http-direct-registry.ts +226 -0
- package/src/driver-test-suite/tests/raw-http-request-properties.ts +414 -0
- package/src/driver-test-suite/tests/raw-http.ts +347 -0
- package/src/driver-test-suite/tests/raw-websocket-direct-registry.ts +392 -0
- package/src/driver-test-suite/tests/raw-websocket.ts +484 -0
- package/src/driver-test-suite/tests/request-access.ts +244 -0
- package/src/driver-test-suite/utils.ts +68 -0
- package/src/drivers/default.ts +31 -0
- package/src/drivers/engine/actor-driver.ts +360 -0
- package/src/drivers/engine/api-endpoints.ts +128 -0
- package/src/drivers/engine/api-utils.ts +70 -0
- package/src/drivers/engine/config.ts +39 -0
- package/src/drivers/engine/keys.test.ts +266 -0
- package/src/drivers/engine/keys.ts +89 -0
- package/src/drivers/engine/kv.ts +3 -0
- package/src/drivers/engine/log.ts +7 -0
- package/src/drivers/engine/manager-driver.ts +391 -0
- package/src/drivers/engine/mod.ts +36 -0
- package/src/drivers/engine/ws-proxy.ts +170 -0
- package/src/drivers/file-system/actor.ts +91 -0
- package/src/drivers/file-system/global-state.ts +673 -0
- package/src/drivers/file-system/log.ts +7 -0
- package/src/drivers/file-system/manager.ts +306 -0
- package/src/drivers/file-system/mod.ts +48 -0
- package/src/drivers/file-system/utils.ts +109 -0
- package/src/globals.d.ts +6 -0
- package/src/inline-client-driver/log.ts +7 -0
- package/src/inline-client-driver/mod.ts +385 -0
- package/src/inspector/actor.ts +298 -0
- package/src/inspector/config.ts +83 -0
- package/src/inspector/log.ts +5 -0
- package/src/inspector/manager.ts +86 -0
- package/src/inspector/mod.ts +2 -0
- package/src/inspector/protocol/actor.ts +10 -0
- package/src/inspector/protocol/common.ts +196 -0
- package/src/inspector/protocol/manager.ts +10 -0
- package/src/inspector/protocol/mod.ts +2 -0
- package/src/inspector/utils.ts +76 -0
- package/src/manager/auth.ts +121 -0
- package/src/manager/driver.ts +80 -0
- package/src/manager/hono-websocket-adapter.ts +333 -0
- package/src/manager/log.ts +7 -0
- package/src/manager/mod.ts +2 -0
- package/src/manager/protocol/mod.ts +24 -0
- package/src/manager/protocol/query.ts +89 -0
- package/src/manager/router.ts +1792 -0
- package/src/mod.ts +20 -0
- package/src/registry/config.ts +32 -0
- package/src/registry/log.ts +7 -0
- package/src/registry/mod.ts +124 -0
- package/src/registry/run-config.ts +54 -0
- package/src/registry/serve.ts +53 -0
- package/src/schemas/actor-persist/mod.ts +1 -0
- package/src/schemas/actor-persist/versioned.ts +25 -0
- package/src/schemas/client-protocol/mod.ts +1 -0
- package/src/schemas/client-protocol/versioned.ts +63 -0
- package/src/schemas/file-system-driver/mod.ts +1 -0
- package/src/schemas/file-system-driver/versioned.ts +28 -0
- package/src/serde.ts +84 -0
- package/src/test/config.ts +16 -0
- package/src/test/log.ts +7 -0
- package/src/test/mod.ts +153 -0
- package/src/utils.ts +172 -0
- package/README.md +0 -13
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
import * as cbor from "cbor-x";
|
|
2
|
+
import type { Context as HonoContext } from "hono";
|
|
3
|
+
import invariant from "invariant";
|
|
4
|
+
import { ActorAlreadyExists } from "@/actor/errors";
|
|
5
|
+
import {
|
|
6
|
+
HEADER_AUTH_DATA,
|
|
7
|
+
HEADER_CONN_PARAMS,
|
|
8
|
+
HEADER_ENCODING,
|
|
9
|
+
HEADER_EXPOSE_INTERNAL_ERROR,
|
|
10
|
+
} from "@/actor/router-endpoints";
|
|
11
|
+
import { generateRandomString } from "@/actor/utils";
|
|
12
|
+
import { importWebSocket } from "@/common/websocket";
|
|
13
|
+
import type {
|
|
14
|
+
ActorOutput,
|
|
15
|
+
CreateInput,
|
|
16
|
+
GetForIdInput,
|
|
17
|
+
GetOrCreateWithKeyInput,
|
|
18
|
+
GetWithKeyInput,
|
|
19
|
+
ManagerDriver,
|
|
20
|
+
} from "@/driver-helpers/mod";
|
|
21
|
+
import { type Encoding, noopNext, type RunConfig } from "@/mod";
|
|
22
|
+
import {
|
|
23
|
+
createActor,
|
|
24
|
+
destroyActor,
|
|
25
|
+
getActor,
|
|
26
|
+
getActorById,
|
|
27
|
+
getOrCreateActorById,
|
|
28
|
+
} from "./api-endpoints";
|
|
29
|
+
import { EngineApiError } from "./api-utils";
|
|
30
|
+
import type { Config } from "./config";
|
|
31
|
+
import { deserializeActorKey, serializeActorKey } from "./keys";
|
|
32
|
+
import { logger } from "./log";
|
|
33
|
+
import { createWebSocketProxy } from "./ws-proxy";
|
|
34
|
+
|
|
35
|
+
export class EngineManagerDriver implements ManagerDriver {
|
|
36
|
+
#config: Config;
|
|
37
|
+
#runConfig: RunConfig;
|
|
38
|
+
#importWebSocketPromise: Promise<typeof WebSocket>;
|
|
39
|
+
|
|
40
|
+
constructor(config: Config, runConfig: RunConfig) {
|
|
41
|
+
this.#config = config;
|
|
42
|
+
this.#runConfig = runConfig;
|
|
43
|
+
if (!this.#runConfig.inspector.token()) {
|
|
44
|
+
const token = generateRandomString();
|
|
45
|
+
this.#runConfig.inspector.token = () => token;
|
|
46
|
+
}
|
|
47
|
+
this.#importWebSocketPromise = importWebSocket();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async sendRequest(actorId: string, actorRequest: Request): Promise<Response> {
|
|
51
|
+
logger().debug("sending request to actor via guard", {
|
|
52
|
+
actorId,
|
|
53
|
+
method: actorRequest.method,
|
|
54
|
+
url: actorRequest.url,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return this.#forwardHttpRequest(actorRequest, actorId);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async openWebSocket(
|
|
61
|
+
path: string,
|
|
62
|
+
actorId: string,
|
|
63
|
+
encoding: Encoding,
|
|
64
|
+
params: unknown,
|
|
65
|
+
): Promise<WebSocket> {
|
|
66
|
+
const WebSocket = await this.#importWebSocketPromise;
|
|
67
|
+
|
|
68
|
+
// WebSocket connections go through guard
|
|
69
|
+
const guardUrl = `${this.#config.endpoint}${path}`;
|
|
70
|
+
|
|
71
|
+
logger().debug("opening websocket to actor via guard", {
|
|
72
|
+
actorId,
|
|
73
|
+
path,
|
|
74
|
+
guardUrl,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Create WebSocket connection
|
|
78
|
+
const ws = new WebSocket(guardUrl, {
|
|
79
|
+
headers: buildGuardHeadersForWebSocket(actorId, encoding, params),
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
logger().debug("websocket connection opened", { actorId });
|
|
83
|
+
|
|
84
|
+
return ws;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async proxyRequest(
|
|
88
|
+
_c: HonoContext,
|
|
89
|
+
actorRequest: Request,
|
|
90
|
+
actorId: string,
|
|
91
|
+
): Promise<Response> {
|
|
92
|
+
logger().debug("forwarding request to actor via guard", {
|
|
93
|
+
actorId,
|
|
94
|
+
method: actorRequest.method,
|
|
95
|
+
url: actorRequest.url,
|
|
96
|
+
hasBody: !!actorRequest.body,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return this.#forwardHttpRequest(actorRequest, actorId);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async proxyWebSocket(
|
|
103
|
+
c: HonoContext,
|
|
104
|
+
path: string,
|
|
105
|
+
actorId: string,
|
|
106
|
+
encoding: Encoding,
|
|
107
|
+
params: unknown,
|
|
108
|
+
authData: unknown,
|
|
109
|
+
): Promise<Response> {
|
|
110
|
+
const upgradeWebSocket = this.#runConfig.getUpgradeWebSocket?.();
|
|
111
|
+
invariant(upgradeWebSocket, "missing getUpgradeWebSocket");
|
|
112
|
+
|
|
113
|
+
const guardUrl = `${this.#config.endpoint}${path}`;
|
|
114
|
+
const wsGuardUrl = guardUrl.replace("http://", "ws://");
|
|
115
|
+
|
|
116
|
+
logger().debug("forwarding websocket to actor via guard", {
|
|
117
|
+
actorId,
|
|
118
|
+
path,
|
|
119
|
+
guardUrl,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Build headers
|
|
123
|
+
const headers = buildGuardHeadersForWebSocket(
|
|
124
|
+
actorId,
|
|
125
|
+
encoding,
|
|
126
|
+
params,
|
|
127
|
+
authData,
|
|
128
|
+
);
|
|
129
|
+
const args = await createWebSocketProxy(c, wsGuardUrl, headers);
|
|
130
|
+
|
|
131
|
+
return await upgradeWebSocket(() => args)(c, noopNext());
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
extraStartupLog() {
|
|
135
|
+
return {
|
|
136
|
+
engine: this.#config.endpoint,
|
|
137
|
+
namespace: this.#config.namespace,
|
|
138
|
+
runner: this.#config.runnerName,
|
|
139
|
+
address: Object.values(this.#config.addresses)
|
|
140
|
+
.map((v) => `${v.host}:${v.port}`)
|
|
141
|
+
.join(", "),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async getForId({
|
|
146
|
+
c,
|
|
147
|
+
name,
|
|
148
|
+
actorId,
|
|
149
|
+
}: GetForIdInput): Promise<ActorOutput | undefined> {
|
|
150
|
+
// Fetch from API if not in cache
|
|
151
|
+
try {
|
|
152
|
+
const response = await getActor(this.#config, actorId);
|
|
153
|
+
|
|
154
|
+
// Validate name matches
|
|
155
|
+
if (response.actor.name !== name) {
|
|
156
|
+
logger().debug("actor name mismatch from api", {
|
|
157
|
+
actorId,
|
|
158
|
+
apiName: response.actor.name,
|
|
159
|
+
requestedName: name,
|
|
160
|
+
});
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const keyRaw = response.actor.key;
|
|
165
|
+
invariant(keyRaw, `actor ${actorId} should have key`);
|
|
166
|
+
const key = deserializeActorKey(keyRaw);
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
actorId,
|
|
170
|
+
name,
|
|
171
|
+
key,
|
|
172
|
+
};
|
|
173
|
+
} catch (error) {
|
|
174
|
+
if (
|
|
175
|
+
error instanceof EngineApiError &&
|
|
176
|
+
(error as EngineApiError).group === "actor" &&
|
|
177
|
+
(error as EngineApiError).code === "not_found"
|
|
178
|
+
) {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async getWithKey({
|
|
186
|
+
c,
|
|
187
|
+
name,
|
|
188
|
+
key,
|
|
189
|
+
}: GetWithKeyInput): Promise<ActorOutput | undefined> {
|
|
190
|
+
logger().debug("getWithKey: searching for actor", { name, key });
|
|
191
|
+
|
|
192
|
+
// If not in local cache, fetch by key from API
|
|
193
|
+
try {
|
|
194
|
+
const response = await getActorById(this.#config, name, key);
|
|
195
|
+
|
|
196
|
+
if (!response.actor_id) {
|
|
197
|
+
return undefined;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const actorId = response.actor_id;
|
|
201
|
+
|
|
202
|
+
logger().debug("getWithKey: found actor via api", {
|
|
203
|
+
actorId,
|
|
204
|
+
name,
|
|
205
|
+
key,
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
actorId,
|
|
210
|
+
name,
|
|
211
|
+
key,
|
|
212
|
+
};
|
|
213
|
+
} catch (error) {
|
|
214
|
+
if (
|
|
215
|
+
error instanceof EngineApiError &&
|
|
216
|
+
(error as EngineApiError).group === "actor" &&
|
|
217
|
+
(error as EngineApiError).code === "not_found"
|
|
218
|
+
) {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
throw error;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async getOrCreateWithKey(
|
|
226
|
+
input: GetOrCreateWithKeyInput,
|
|
227
|
+
): Promise<ActorOutput> {
|
|
228
|
+
const { c, name, key, input: actorInput, region } = input;
|
|
229
|
+
|
|
230
|
+
logger().info(
|
|
231
|
+
"getOrCreateWithKey: getting or creating actor via engine api",
|
|
232
|
+
{
|
|
233
|
+
name,
|
|
234
|
+
key,
|
|
235
|
+
},
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
const response = await getOrCreateActorById(this.#config, {
|
|
239
|
+
name,
|
|
240
|
+
key: serializeActorKey(key),
|
|
241
|
+
runner_name_selector: this.#config.runnerName,
|
|
242
|
+
input: input ? cbor.encode(actorInput).toString("base64") : undefined,
|
|
243
|
+
crash_policy: "sleep",
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
const actorId = response.actor_id;
|
|
247
|
+
|
|
248
|
+
logger().info("getOrCreateWithKey: actor ready", {
|
|
249
|
+
actorId,
|
|
250
|
+
name,
|
|
251
|
+
key,
|
|
252
|
+
created: response.created,
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
return {
|
|
256
|
+
actorId,
|
|
257
|
+
name,
|
|
258
|
+
key,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
async createActor({
|
|
263
|
+
c,
|
|
264
|
+
name,
|
|
265
|
+
key,
|
|
266
|
+
input,
|
|
267
|
+
}: CreateInput): Promise<ActorOutput> {
|
|
268
|
+
// Check if actor with the same name and key already exists
|
|
269
|
+
const existingActor = await this.getWithKey({ c, name, key });
|
|
270
|
+
if (existingActor) {
|
|
271
|
+
throw new ActorAlreadyExists(name, key);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
logger().info("creating actor via engine api", { name, key });
|
|
275
|
+
|
|
276
|
+
// Create actor via engine API
|
|
277
|
+
const result = await createActor(this.#config, {
|
|
278
|
+
name,
|
|
279
|
+
runner_name_selector: this.#config.runnerName,
|
|
280
|
+
key: serializeActorKey(key),
|
|
281
|
+
input: input ? cbor.encode(input).toString("base64") : null,
|
|
282
|
+
crash_policy: "sleep",
|
|
283
|
+
});
|
|
284
|
+
const actorId = result.actor.actor_id;
|
|
285
|
+
|
|
286
|
+
logger().info("actor created", { actorId, name, key });
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
actorId,
|
|
290
|
+
name,
|
|
291
|
+
key,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
async destroyActor(actorId: string): Promise<void> {
|
|
296
|
+
logger().info("destroying actor via engine api", { actorId });
|
|
297
|
+
|
|
298
|
+
await destroyActor(this.#config, actorId);
|
|
299
|
+
|
|
300
|
+
logger().info("actor destroyed", { actorId });
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async #forwardHttpRequest(
|
|
304
|
+
actorRequest: Request,
|
|
305
|
+
actorId: string,
|
|
306
|
+
): Promise<Response> {
|
|
307
|
+
// Route through guard port
|
|
308
|
+
const url = new URL(actorRequest.url);
|
|
309
|
+
const guardUrl = `${this.#config.endpoint}${url.pathname}${url.search}`;
|
|
310
|
+
|
|
311
|
+
// Handle body properly based on method and presence
|
|
312
|
+
let bodyToSend: ArrayBuffer | null = null;
|
|
313
|
+
const guardHeaders = buildGuardHeadersForHttp(actorRequest, actorId);
|
|
314
|
+
|
|
315
|
+
if (
|
|
316
|
+
actorRequest.body &&
|
|
317
|
+
actorRequest.method !== "GET" &&
|
|
318
|
+
actorRequest.method !== "HEAD"
|
|
319
|
+
) {
|
|
320
|
+
if (actorRequest.bodyUsed) {
|
|
321
|
+
throw new Error("Request body has already been consumed");
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// TODO: This buffers the entire request in memory every time. We
|
|
325
|
+
// need to properly implement streaming bodies.
|
|
326
|
+
// Clone and read the body to ensure it can be sent
|
|
327
|
+
const clonedRequest = actorRequest.clone();
|
|
328
|
+
bodyToSend = await clonedRequest.arrayBuffer();
|
|
329
|
+
|
|
330
|
+
// If this is a streaming request, we need to convert the headers
|
|
331
|
+
// for the basic array buffer
|
|
332
|
+
guardHeaders.delete("transfer-encoding");
|
|
333
|
+
guardHeaders.set(
|
|
334
|
+
"content-length",
|
|
335
|
+
String((bodyToSend as ArrayBuffer).byteLength),
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const guardRequest = new Request(guardUrl, {
|
|
340
|
+
method: actorRequest.method,
|
|
341
|
+
headers: guardHeaders,
|
|
342
|
+
body: bodyToSend,
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
return mutableResponse(await fetch(guardRequest));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function mutableResponse(fetchRes: Response): Response {
|
|
350
|
+
// We cannot return the raw response from `fetch` since the response type is not mutable.
|
|
351
|
+
//
|
|
352
|
+
// In order for middleware to be able to mutate the response, we need to build a new Response object that is mutable.
|
|
353
|
+
return new Response(fetchRes.body, fetchRes);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function buildGuardHeadersForHttp(
|
|
357
|
+
actorRequest: Request,
|
|
358
|
+
actorId: string,
|
|
359
|
+
): Headers {
|
|
360
|
+
const headers = new Headers();
|
|
361
|
+
// Copy all headers from the original request
|
|
362
|
+
for (const [key, value] of actorRequest.headers.entries()) {
|
|
363
|
+
headers.set(key, value);
|
|
364
|
+
}
|
|
365
|
+
// Add guard-specific headers
|
|
366
|
+
headers.set("x-rivet-target", "actor");
|
|
367
|
+
headers.set("x-rivet-actor", actorId);
|
|
368
|
+
headers.set("x-rivet-port", "main");
|
|
369
|
+
return headers;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function buildGuardHeadersForWebSocket(
|
|
373
|
+
actorId: string,
|
|
374
|
+
encoding: Encoding,
|
|
375
|
+
params?: unknown,
|
|
376
|
+
authData?: unknown,
|
|
377
|
+
): Record<string, string> {
|
|
378
|
+
const headers: Record<string, string> = {};
|
|
379
|
+
headers["x-rivet-target"] = "actor";
|
|
380
|
+
headers["x-rivet-actor"] = actorId;
|
|
381
|
+
headers["x-rivet-port"] = "main";
|
|
382
|
+
headers[HEADER_EXPOSE_INTERNAL_ERROR] = "true";
|
|
383
|
+
headers[HEADER_ENCODING] = encoding;
|
|
384
|
+
if (params) {
|
|
385
|
+
headers[HEADER_CONN_PARAMS] = JSON.stringify(params);
|
|
386
|
+
}
|
|
387
|
+
if (authData) {
|
|
388
|
+
headers[HEADER_AUTH_DATA] = JSON.stringify(authData);
|
|
389
|
+
}
|
|
390
|
+
return headers;
|
|
391
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Client } from "@/client/client";
|
|
2
|
+
import type { ManagerDriver } from "@/manager/driver";
|
|
3
|
+
import type { RegistryConfig } from "@/registry/config";
|
|
4
|
+
import type { DriverConfig, RunConfig } from "@/registry/run-config";
|
|
5
|
+
import { EngineActorDriver } from "./actor-driver";
|
|
6
|
+
import { ConfigSchema, type InputConfig } from "./config";
|
|
7
|
+
import { EngineManagerDriver } from "./manager-driver";
|
|
8
|
+
|
|
9
|
+
export { EngineActorDriver } from "./actor-driver";
|
|
10
|
+
export { type Config, ConfigSchema, type InputConfig } from "./config";
|
|
11
|
+
export { EngineManagerDriver } from "./manager-driver";
|
|
12
|
+
|
|
13
|
+
export function createEngineDriver(inputConfig?: InputConfig): DriverConfig {
|
|
14
|
+
const config = ConfigSchema.parse(inputConfig);
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
name: "engine",
|
|
18
|
+
manager: (_registryConfig, runConfig) => {
|
|
19
|
+
return new EngineManagerDriver(config, runConfig);
|
|
20
|
+
},
|
|
21
|
+
actor: (
|
|
22
|
+
registryConfig: RegistryConfig,
|
|
23
|
+
runConfig: RunConfig,
|
|
24
|
+
managerDriver: ManagerDriver,
|
|
25
|
+
inlineClient: Client<any>,
|
|
26
|
+
) => {
|
|
27
|
+
return new EngineActorDriver(
|
|
28
|
+
registryConfig,
|
|
29
|
+
runConfig,
|
|
30
|
+
managerDriver,
|
|
31
|
+
inlineClient,
|
|
32
|
+
config,
|
|
33
|
+
);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import type { Context as HonoContext } from "hono";
|
|
2
|
+
import type { WSContext } from "hono/ws";
|
|
3
|
+
import invariant from "invariant";
|
|
4
|
+
import type { CloseEvent } from "ws";
|
|
5
|
+
import { importWebSocket } from "@/common/websocket";
|
|
6
|
+
import type { UpgradeWebSocketArgs } from "@/mod";
|
|
7
|
+
import { logger } from "./log";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Returns Hono `upgradeWebSocket` args that will proxy requests from the client to a destination address.
|
|
11
|
+
*/
|
|
12
|
+
export async function createWebSocketProxy(
|
|
13
|
+
c: HonoContext,
|
|
14
|
+
targetUrl: string,
|
|
15
|
+
headers: Record<string, string>,
|
|
16
|
+
): Promise<UpgradeWebSocketArgs> {
|
|
17
|
+
const WebSocket = await importWebSocket();
|
|
18
|
+
|
|
19
|
+
// HACK: Sanitize WebSocket-specific headers. If we don't do this, some WebSocket implementations (i.e. native WebSocket in Node.js) will fail to connect.
|
|
20
|
+
for (const [k, v] of c.req.raw.headers.entries()) {
|
|
21
|
+
if (!k.startsWith("sec-") && k !== "connection" && k !== "upgrade") {
|
|
22
|
+
headers[k] = v;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// WebSocket state
|
|
27
|
+
interface WsState {
|
|
28
|
+
targetWs?: WebSocket;
|
|
29
|
+
connectPromise?: Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
const state: WsState = {};
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
onOpen: async (event: any, clientWs: WSContext) => {
|
|
35
|
+
logger().debug("client websocket connected", { targetUrl });
|
|
36
|
+
|
|
37
|
+
if (clientWs.readyState !== 1) {
|
|
38
|
+
logger().warn("client websocket not open on connection", {
|
|
39
|
+
targetUrl,
|
|
40
|
+
readyState: clientWs.readyState,
|
|
41
|
+
});
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Create WebSocket
|
|
46
|
+
const targetWs = new WebSocket(targetUrl, { headers });
|
|
47
|
+
state.targetWs = targetWs;
|
|
48
|
+
|
|
49
|
+
// Setup connection promise
|
|
50
|
+
state.connectPromise = new Promise<void>((resolve, reject) => {
|
|
51
|
+
targetWs.addEventListener("open", () => {
|
|
52
|
+
logger().debug("target websocket connected", { targetUrl });
|
|
53
|
+
|
|
54
|
+
if (clientWs.readyState !== 1) {
|
|
55
|
+
logger().warn("client websocket closed before target connected", {
|
|
56
|
+
targetUrl,
|
|
57
|
+
clientReadyState: clientWs.readyState,
|
|
58
|
+
});
|
|
59
|
+
targetWs.close(1001, "Client disconnected");
|
|
60
|
+
reject(new Error("Client disconnected"));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
resolve();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
targetWs.addEventListener("error", (error) => {
|
|
67
|
+
logger().warn("target websocket error during connection", {
|
|
68
|
+
targetUrl,
|
|
69
|
+
});
|
|
70
|
+
reject(error);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Setup bidirectional forwarding
|
|
75
|
+
state.targetWs.addEventListener("message", (event) => {
|
|
76
|
+
if (
|
|
77
|
+
typeof event.data === "string" ||
|
|
78
|
+
event.data instanceof ArrayBuffer
|
|
79
|
+
) {
|
|
80
|
+
clientWs.send(event.data);
|
|
81
|
+
} else if (event.data instanceof Blob) {
|
|
82
|
+
event.data.arrayBuffer().then((buffer) => {
|
|
83
|
+
clientWs.send(buffer);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
state.targetWs.addEventListener("close", (event) => {
|
|
89
|
+
logger().debug("target websocket closed", {
|
|
90
|
+
targetUrl,
|
|
91
|
+
code: event.code,
|
|
92
|
+
reason: event.reason,
|
|
93
|
+
});
|
|
94
|
+
closeWebSocketIfOpen(clientWs, event.code, event.reason);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
state.targetWs.addEventListener("error", (error) => {
|
|
98
|
+
logger().error("target websocket error", { targetUrl, error });
|
|
99
|
+
closeWebSocketIfOpen(clientWs, 1011, "Target WebSocket error");
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
onMessage: async (event: any, clientWs: WSContext) => {
|
|
104
|
+
if (!state.targetWs || !state.connectPromise) {
|
|
105
|
+
logger().error("websocket state not initialized", { targetUrl });
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
await state.connectPromise;
|
|
111
|
+
if (state.targetWs.readyState === WebSocket.OPEN) {
|
|
112
|
+
state.targetWs.send(event.data);
|
|
113
|
+
} else {
|
|
114
|
+
logger().warn("target websocket not open", {
|
|
115
|
+
targetUrl,
|
|
116
|
+
readyState: state.targetWs.readyState,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
} catch (error) {
|
|
120
|
+
logger().error("failed to connect to target websocket", {
|
|
121
|
+
targetUrl,
|
|
122
|
+
error,
|
|
123
|
+
});
|
|
124
|
+
closeWebSocketIfOpen(clientWs, 1011, "Failed to connect to target");
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
onClose: (event: any, clientWs: WSContext) => {
|
|
129
|
+
logger().debug("client websocket closed", {
|
|
130
|
+
targetUrl,
|
|
131
|
+
code: event.code,
|
|
132
|
+
reason: event.reason,
|
|
133
|
+
wasClean: event.wasClean,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
if (state.targetWs) {
|
|
137
|
+
if (
|
|
138
|
+
state.targetWs.readyState === WebSocket.OPEN ||
|
|
139
|
+
state.targetWs.readyState === WebSocket.CONNECTING
|
|
140
|
+
) {
|
|
141
|
+
state.targetWs.close(1000, event.reason || "Client disconnected");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
onError: (event: any, clientWs: WSContext) => {
|
|
147
|
+
logger().error("client websocket error", { targetUrl, event });
|
|
148
|
+
|
|
149
|
+
if (state.targetWs) {
|
|
150
|
+
if (state.targetWs.readyState === WebSocket.OPEN) {
|
|
151
|
+
state.targetWs.close(1011, "Client WebSocket error");
|
|
152
|
+
} else if (state.targetWs.readyState === WebSocket.CONNECTING) {
|
|
153
|
+
state.targetWs.close();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function closeWebSocketIfOpen(
|
|
161
|
+
ws: WebSocket | WSContext,
|
|
162
|
+
code: number,
|
|
163
|
+
reason: string,
|
|
164
|
+
): void {
|
|
165
|
+
if (ws.readyState === 1) {
|
|
166
|
+
ws.close(code, reason);
|
|
167
|
+
} else if ("close" in ws && (ws as WebSocket).readyState === WebSocket.OPEN) {
|
|
168
|
+
ws.close(code, reason);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { GenericConnGlobalState } from "@/actor/generic-conn-driver";
|
|
2
|
+
import { logger } from "@/actor/log";
|
|
3
|
+
import type { AnyClient } from "@/client/client";
|
|
4
|
+
import type {
|
|
5
|
+
ActorDriver,
|
|
6
|
+
AnyActorInstance,
|
|
7
|
+
ManagerDriver,
|
|
8
|
+
} from "@/driver-helpers/mod";
|
|
9
|
+
import type { RegistryConfig, RunConfig } from "@/mod";
|
|
10
|
+
import { bufferToArrayBuffer } from "@/utils";
|
|
11
|
+
import type { FileSystemGlobalState } from "./global-state";
|
|
12
|
+
|
|
13
|
+
export type ActorDriverContext = Record<never, never>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* File System implementation of the Actor Driver
|
|
17
|
+
*/
|
|
18
|
+
export class FileSystemActorDriver implements ActorDriver {
|
|
19
|
+
#registryConfig: RegistryConfig;
|
|
20
|
+
#runConfig: RunConfig;
|
|
21
|
+
#managerDriver: ManagerDriver;
|
|
22
|
+
#inlineClient: AnyClient;
|
|
23
|
+
#state: FileSystemGlobalState;
|
|
24
|
+
|
|
25
|
+
constructor(
|
|
26
|
+
registryConfig: RegistryConfig,
|
|
27
|
+
runConfig: RunConfig,
|
|
28
|
+
managerDriver: ManagerDriver,
|
|
29
|
+
inlineClient: AnyClient,
|
|
30
|
+
state: FileSystemGlobalState,
|
|
31
|
+
) {
|
|
32
|
+
this.#registryConfig = registryConfig;
|
|
33
|
+
this.#runConfig = runConfig;
|
|
34
|
+
this.#managerDriver = managerDriver;
|
|
35
|
+
this.#inlineClient = inlineClient;
|
|
36
|
+
this.#state = state;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async loadActor(actorId: string): Promise<AnyActorInstance> {
|
|
40
|
+
return this.#state.startActor(
|
|
41
|
+
this.#registryConfig,
|
|
42
|
+
this.#runConfig,
|
|
43
|
+
this.#inlineClient,
|
|
44
|
+
this,
|
|
45
|
+
actorId,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
getGenericConnGlobalState(actorId: string): GenericConnGlobalState {
|
|
50
|
+
return this.#state.getActorOrError(actorId).genericConnGlobalState;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get the current storage directory path
|
|
55
|
+
*/
|
|
56
|
+
get storagePath(): string {
|
|
57
|
+
return this.#state.storagePath;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
getContext(_actorId: string): ActorDriverContext {
|
|
61
|
+
return {};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async readPersistedData(actorId: string): Promise<Uint8Array | undefined> {
|
|
65
|
+
return new Uint8Array(
|
|
66
|
+
(await this.#state.loadActorStateOrError(actorId)).persistedData,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async writePersistedData(actorId: string, data: Uint8Array): Promise<void> {
|
|
71
|
+
const state = await this.#state.loadActorStateOrError(actorId);
|
|
72
|
+
|
|
73
|
+
// Save state to disk
|
|
74
|
+
await this.#state.writeActor(actorId, {
|
|
75
|
+
...state,
|
|
76
|
+
persistedData: bufferToArrayBuffer(data),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async setAlarm(actor: AnyActorInstance, timestamp: number): Promise<void> {
|
|
81
|
+
await this.#state.setActorAlarm(actor.id, timestamp);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
getDatabase(actorId: string): Promise<unknown | undefined> {
|
|
85
|
+
return this.#state.createDatabase(actorId);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
sleep(actorId: string): Promise<void> {
|
|
89
|
+
return this.#state.sleepActor(actorId);
|
|
90
|
+
}
|
|
91
|
+
}
|