rivetkit 2.0.5 → 2.0.7-rc.1
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 +0 -6
- package/dist/tsup/actor-router-consts-B3Lu87yJ.d.cts +28 -0
- package/dist/tsup/actor-router-consts-B3Lu87yJ.d.ts +28 -0
- package/dist/tsup/{chunk-5YTI25C3.cjs → chunk-3MBP4WNC.cjs} +7 -7
- package/dist/tsup/{chunk-5YTI25C3.cjs.map → chunk-3MBP4WNC.cjs.map} +1 -1
- package/dist/tsup/chunk-3Y45CIF4.cjs +3726 -0
- package/dist/tsup/chunk-3Y45CIF4.cjs.map +1 -0
- package/dist/tsup/chunk-4GP7BZSR.js +102 -0
- package/dist/tsup/chunk-4GP7BZSR.js.map +1 -0
- package/dist/tsup/chunk-5ZOHIKWG.cjs +4071 -0
- package/dist/tsup/chunk-5ZOHIKWG.cjs.map +1 -0
- package/dist/tsup/{chunk-WADSS5X4.cjs → chunk-6EUWRXLT.cjs} +21 -7
- package/dist/tsup/chunk-6EUWRXLT.cjs.map +1 -0
- package/dist/tsup/{chunk-D7NWUCRK.cjs → chunk-6OVKCDSH.cjs} +6 -6
- package/dist/tsup/{chunk-D7NWUCRK.cjs.map → chunk-6OVKCDSH.cjs.map} +1 -1
- package/dist/tsup/{chunk-I5VTWPHW.js → chunk-7N56ZUC7.js} +3 -3
- package/dist/tsup/{chunk-LZIBTLEY.cjs → chunk-B3TLRM4Q.cjs} +13 -25
- package/dist/tsup/chunk-B3TLRM4Q.cjs.map +1 -0
- package/dist/tsup/chunk-BW5DPM6Z.js +4071 -0
- package/dist/tsup/chunk-BW5DPM6Z.js.map +1 -0
- package/dist/tsup/chunk-DFS77KAA.cjs +1046 -0
- package/dist/tsup/chunk-DFS77KAA.cjs.map +1 -0
- package/dist/tsup/{chunk-PG3K2LI7.js → chunk-E4UVJKSV.js} +2 -2
- package/dist/tsup/chunk-G4ABMAQY.cjs +102 -0
- package/dist/tsup/chunk-G4ABMAQY.cjs.map +1 -0
- package/dist/tsup/{chunk-CKA54YQN.js → chunk-GZVBFXBI.js} +3 -15
- package/dist/tsup/chunk-GZVBFXBI.js.map +1 -0
- package/dist/tsup/chunk-HPT3I7UU.js +3726 -0
- package/dist/tsup/chunk-HPT3I7UU.js.map +1 -0
- package/dist/tsup/chunk-JD54PXWP.js +1046 -0
- package/dist/tsup/chunk-JD54PXWP.js.map +1 -0
- package/dist/tsup/{chunk-PHSQJ6QI.cjs → chunk-K4ENQCC4.cjs} +3 -3
- package/dist/tsup/{chunk-PHSQJ6QI.cjs.map → chunk-K4ENQCC4.cjs.map} +1 -1
- package/dist/tsup/{chunk-WNGOBAA7.js → chunk-PUSQNDJG.js} +2 -2
- package/dist/tsup/{chunk-CFFKMUYH.js → chunk-RVP5RUSC.js} +20 -6
- package/dist/tsup/chunk-RVP5RUSC.js.map +1 -0
- package/dist/tsup/chunk-SAZCNSVY.cjs +259 -0
- package/dist/tsup/chunk-SAZCNSVY.cjs.map +1 -0
- package/dist/tsup/{chunk-YW6Y6VNE.js → chunk-SBKRVQS2.js} +9 -5
- package/dist/tsup/chunk-SBKRVQS2.js.map +1 -0
- package/dist/tsup/{chunk-FGFT4FVX.cjs → chunk-TZGUSEIJ.cjs} +14 -10
- package/dist/tsup/chunk-TZGUSEIJ.cjs.map +1 -0
- package/dist/tsup/chunk-YQ4XQYPM.js +259 -0
- package/dist/tsup/chunk-YQ4XQYPM.js.map +1 -0
- package/dist/tsup/client/mod.cjs +9 -9
- package/dist/tsup/client/mod.d.cts +7 -8
- package/dist/tsup/client/mod.d.ts +7 -8
- package/dist/tsup/client/mod.js +8 -8
- package/dist/tsup/common/log.cjs +3 -3
- package/dist/tsup/common/log.js +2 -2
- package/dist/tsup/common/websocket.cjs +4 -4
- package/dist/tsup/common/websocket.js +3 -3
- package/dist/tsup/{connection-BvE-Oq7t.d.ts → conn-DCSQgIlw.d.ts} +1605 -1353
- package/dist/tsup/{connection-DTzmWwU5.d.cts → conn-DdzHTm2E.d.cts} +1605 -1353
- package/dist/tsup/driver-helpers/mod.cjs +31 -5
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -1
- package/dist/tsup/driver-helpers/mod.d.cts +7 -8
- package/dist/tsup/driver-helpers/mod.d.ts +7 -8
- package/dist/tsup/driver-helpers/mod.js +33 -7
- package/dist/tsup/driver-test-suite/mod.cjs +319 -216
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/driver-test-suite/mod.d.cts +7 -7
- package/dist/tsup/driver-test-suite/mod.d.ts +7 -7
- package/dist/tsup/driver-test-suite/mod.js +588 -485
- package/dist/tsup/driver-test-suite/mod.js.map +1 -1
- package/dist/tsup/inspector/mod.cjs +17 -5
- package/dist/tsup/inspector/mod.cjs.map +1 -1
- package/dist/tsup/inspector/mod.d.cts +34 -7
- package/dist/tsup/inspector/mod.d.ts +34 -7
- package/dist/tsup/inspector/mod.js +20 -8
- package/dist/tsup/mod.cjs +10 -17
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +56 -9
- package/dist/tsup/mod.d.ts +56 -9
- package/dist/tsup/mod.js +17 -24
- package/dist/tsup/test/mod.cjs +11 -9
- package/dist/tsup/test/mod.cjs.map +1 -1
- package/dist/tsup/test/mod.d.cts +6 -7
- package/dist/tsup/test/mod.d.ts +6 -7
- package/dist/tsup/test/mod.js +10 -8
- package/dist/tsup/utils.cjs +4 -2
- package/dist/tsup/utils.cjs.map +1 -1
- package/dist/tsup/utils.d.cts +11 -1
- package/dist/tsup/utils.d.ts +11 -1
- package/dist/tsup/utils.js +3 -1
- package/package.json +8 -4
- package/src/actor/action.ts +1 -1
- package/src/actor/config.ts +1 -1
- package/src/actor/conn-drivers.ts +205 -0
- package/src/actor/conn-socket.ts +6 -0
- package/src/actor/{connection.ts → conn.ts} +78 -84
- package/src/actor/context.ts +1 -1
- package/src/actor/driver.ts +4 -43
- package/src/actor/instance.ts +162 -86
- package/src/actor/mod.ts +6 -14
- package/src/actor/persisted.ts +2 -5
- package/src/actor/protocol/old.ts +1 -1
- package/src/actor/router-endpoints.ts +147 -138
- package/src/actor/router.ts +89 -52
- package/src/actor/utils.ts +5 -1
- package/src/client/actor-conn.ts +163 -31
- package/src/client/actor-handle.ts +0 -1
- package/src/client/client.ts +2 -2
- package/src/client/config.ts +7 -0
- package/src/client/raw-utils.ts +1 -1
- package/src/client/utils.ts +1 -1
- package/src/common/actor-router-consts.ts +59 -0
- package/src/common/router.ts +2 -1
- package/src/common/versioned-data.ts +5 -5
- package/src/driver-helpers/mod.ts +15 -2
- package/src/driver-test-suite/mod.ts +11 -2
- package/src/driver-test-suite/test-inline-client-driver.ts +40 -22
- package/src/driver-test-suite/tests/actor-conn-state.ts +66 -22
- package/src/driver-test-suite/tests/actor-conn.ts +65 -126
- package/src/driver-test-suite/tests/actor-reconnect.ts +160 -0
- package/src/driver-test-suite/tests/actor-sleep.ts +0 -1
- package/src/driver-test-suite/tests/raw-websocket.ts +0 -35
- package/src/driver-test-suite/utils.ts +8 -3
- package/src/drivers/default.ts +8 -7
- package/src/drivers/engine/actor-driver.ts +67 -44
- package/src/drivers/engine/config.ts +4 -0
- package/src/drivers/file-system/actor.ts +0 -6
- package/src/drivers/file-system/global-state.ts +3 -14
- package/src/drivers/file-system/manager.ts +12 -8
- package/src/inspector/actor.ts +4 -3
- package/src/inspector/config.ts +10 -1
- package/src/inspector/mod.ts +1 -0
- package/src/inspector/utils.ts +23 -4
- package/src/manager/driver.ts +12 -2
- package/src/manager/gateway.ts +407 -0
- package/src/manager/protocol/query.ts +1 -1
- package/src/manager/router.ts +269 -468
- package/src/manager-api/actors.ts +61 -0
- package/src/manager-api/common.ts +4 -0
- package/src/mod.ts +1 -1
- package/src/registry/mod.ts +126 -12
- package/src/registry/serve.ts +8 -3
- package/src/remote-manager-driver/actor-http-client.ts +30 -19
- package/src/remote-manager-driver/actor-websocket-client.ts +45 -18
- package/src/remote-manager-driver/api-endpoints.ts +19 -21
- package/src/remote-manager-driver/api-utils.ts +10 -1
- package/src/remote-manager-driver/mod.ts +53 -53
- package/src/remote-manager-driver/ws-proxy.ts +2 -9
- package/src/test/mod.ts +6 -2
- package/src/utils.ts +21 -2
- package/dist/tsup/chunk-2MD57QF4.js +0 -1794
- package/dist/tsup/chunk-2MD57QF4.js.map +0 -1
- package/dist/tsup/chunk-B2QGJGZQ.js +0 -338
- package/dist/tsup/chunk-B2QGJGZQ.js.map +0 -1
- package/dist/tsup/chunk-CFFKMUYH.js.map +0 -1
- package/dist/tsup/chunk-CKA54YQN.js.map +0 -1
- package/dist/tsup/chunk-FGFT4FVX.cjs.map +0 -1
- package/dist/tsup/chunk-IRMBWX36.cjs +0 -1794
- package/dist/tsup/chunk-IRMBWX36.cjs.map +0 -1
- package/dist/tsup/chunk-L7QRXNWP.js +0 -6562
- package/dist/tsup/chunk-L7QRXNWP.js.map +0 -1
- package/dist/tsup/chunk-LZIBTLEY.cjs.map +0 -1
- package/dist/tsup/chunk-MRZS2J4X.cjs +0 -6562
- package/dist/tsup/chunk-MRZS2J4X.cjs.map +0 -1
- package/dist/tsup/chunk-RM2SVURR.cjs +0 -338
- package/dist/tsup/chunk-RM2SVURR.cjs.map +0 -1
- package/dist/tsup/chunk-WADSS5X4.cjs.map +0 -1
- package/dist/tsup/chunk-YW6Y6VNE.js.map +0 -1
- package/dist/tsup/common-CXCe7s6i.d.cts +0 -218
- package/dist/tsup/common-CXCe7s6i.d.ts +0 -218
- package/dist/tsup/router-endpoints-CctffZNL.d.cts +0 -65
- package/dist/tsup/router-endpoints-DFm1BglJ.d.ts +0 -65
- package/src/actor/generic-conn-driver.ts +0 -246
- package/src/common/fake-event-source.ts +0 -267
- package/src/manager-api/routes/actors-create.ts +0 -16
- package/src/manager-api/routes/actors-delete.ts +0 -4
- package/src/manager-api/routes/actors-get-by-id.ts +0 -7
- package/src/manager-api/routes/actors-get-or-create-by-id.ts +0 -29
- package/src/manager-api/routes/actors-get.ts +0 -7
- package/src/manager-api/routes/common.ts +0 -18
- /package/dist/tsup/{chunk-I5VTWPHW.js.map → chunk-7N56ZUC7.js.map} +0 -0
- /package/dist/tsup/{chunk-PG3K2LI7.js.map → chunk-E4UVJKSV.js.map} +0 -0
- /package/dist/tsup/{chunk-WNGOBAA7.js.map → chunk-PUSQNDJG.js.map} +0 -0
|
@@ -2,19 +2,26 @@ import * as cbor from "cbor-x";
|
|
|
2
2
|
import type { Context as HonoContext, HonoRequest } from "hono";
|
|
3
3
|
import { type SSEStreamingApi, streamSSE } from "hono/streaming";
|
|
4
4
|
import type { WSContext } from "hono/ws";
|
|
5
|
+
import invariant from "invariant";
|
|
5
6
|
import { ActionContext } from "@/actor/action";
|
|
6
|
-
import type { AnyConn } from "@/actor/
|
|
7
|
+
import type { AnyConn } from "@/actor/conn";
|
|
7
8
|
import {
|
|
8
|
-
CONNECTION_DRIVER_HTTP,
|
|
9
|
-
CONNECTION_DRIVER_SSE,
|
|
10
|
-
CONNECTION_DRIVER_WEBSOCKET,
|
|
11
9
|
generateConnId,
|
|
10
|
+
generateConnSocketId,
|
|
12
11
|
generateConnToken,
|
|
13
|
-
} from "@/actor/
|
|
12
|
+
} from "@/actor/conn";
|
|
13
|
+
import { ConnDriverKind } from "@/actor/conn-drivers";
|
|
14
14
|
import * as errors from "@/actor/errors";
|
|
15
15
|
import type { AnyActorInstance } from "@/actor/instance";
|
|
16
16
|
import type { InputData } from "@/actor/protocol/serde";
|
|
17
17
|
import { type Encoding, EncodingSchema } from "@/actor/protocol/serde";
|
|
18
|
+
import {
|
|
19
|
+
HEADER_ACTOR_QUERY,
|
|
20
|
+
HEADER_CONN_ID,
|
|
21
|
+
HEADER_CONN_PARAMS,
|
|
22
|
+
HEADER_CONN_TOKEN,
|
|
23
|
+
HEADER_ENCODING,
|
|
24
|
+
} from "@/common/actor-router-consts";
|
|
18
25
|
import type { UpgradeWebSocketArgs } from "@/common/inline-websocket-adapter2";
|
|
19
26
|
import { deconstructError, stringifyError } from "@/common/utils";
|
|
20
27
|
import type { UniversalWebSocket } from "@/common/websocket-interface";
|
|
@@ -31,22 +38,18 @@ import {
|
|
|
31
38
|
deserializeWithEncoding,
|
|
32
39
|
serializeWithEncoding,
|
|
33
40
|
} from "@/serde";
|
|
34
|
-
import { bufferToArrayBuffer } from "@/utils";
|
|
41
|
+
import { bufferToArrayBuffer, promiseWithResolvers } from "@/utils";
|
|
35
42
|
import type { ActorDriver } from "./driver";
|
|
36
|
-
import type {
|
|
37
|
-
GenericHttpDriverState,
|
|
38
|
-
GenericSseDriverState,
|
|
39
|
-
GenericWebSocketDriverState,
|
|
40
|
-
} from "./generic-conn-driver";
|
|
41
43
|
import { loggerWithoutContext } from "./log";
|
|
42
44
|
import { parseMessage } from "./protocol/old";
|
|
43
45
|
|
|
46
|
+
export const SSE_PING_INTERVAL = 1000;
|
|
47
|
+
|
|
44
48
|
export interface ConnectWebSocketOpts {
|
|
45
49
|
req?: HonoRequest;
|
|
46
50
|
encoding: Encoding;
|
|
47
51
|
actorId: string;
|
|
48
52
|
params: unknown;
|
|
49
|
-
authData: unknown;
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
export interface ConnectWebSocketOutput {
|
|
@@ -60,7 +63,6 @@ export interface ConnectSseOpts {
|
|
|
60
63
|
encoding: Encoding;
|
|
61
64
|
params: unknown;
|
|
62
65
|
actorId: string;
|
|
63
|
-
authData: unknown;
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
export interface ConnectSseOutput {
|
|
@@ -74,7 +76,6 @@ export interface ActionOpts {
|
|
|
74
76
|
actionName: string;
|
|
75
77
|
actionArgs: unknown[];
|
|
76
78
|
actorId: string;
|
|
77
|
-
authData: unknown;
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
export interface ActionOutput {
|
|
@@ -92,14 +93,12 @@ export interface ConnsMessageOpts {
|
|
|
92
93
|
export interface FetchOpts {
|
|
93
94
|
request: Request;
|
|
94
95
|
actorId: string;
|
|
95
|
-
authData: unknown;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
export interface WebSocketOpts {
|
|
99
99
|
request: Request;
|
|
100
100
|
websocket: UniversalWebSocket;
|
|
101
101
|
actorId: string;
|
|
102
|
-
authData: unknown;
|
|
103
102
|
}
|
|
104
103
|
|
|
105
104
|
/**
|
|
@@ -112,7 +111,8 @@ export async function handleWebSocketConnect(
|
|
|
112
111
|
actorId: string,
|
|
113
112
|
encoding: Encoding,
|
|
114
113
|
parameters: unknown,
|
|
115
|
-
|
|
114
|
+
connId?: string,
|
|
115
|
+
connToken?: string,
|
|
116
116
|
): Promise<UpgradeWebSocketArgs> {
|
|
117
117
|
const exposeInternalError = req ? getRequestExposeInternalError(req) : false;
|
|
118
118
|
|
|
@@ -121,7 +121,7 @@ export async function handleWebSocketConnect(
|
|
|
121
121
|
promise: handlersPromise,
|
|
122
122
|
resolve: handlersResolve,
|
|
123
123
|
reject: handlersReject,
|
|
124
|
-
} =
|
|
124
|
+
} = promiseWithResolvers<{
|
|
125
125
|
conn: AnyConn;
|
|
126
126
|
actor: AnyActorInstance;
|
|
127
127
|
connId: string;
|
|
@@ -153,40 +153,47 @@ export async function handleWebSocketConnect(
|
|
|
153
153
|
};
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
// Promise used to wait for the websocket close in `disconnect`
|
|
157
|
+
const closePromise = promiseWithResolvers<void>();
|
|
158
|
+
const socketId = generateConnSocketId();
|
|
159
|
+
|
|
156
160
|
return {
|
|
157
161
|
onOpen: (_evt: any, ws: WSContext) => {
|
|
158
|
-
actor.rLog.debug("websocket open");
|
|
162
|
+
actor.rLog.debug("actor websocket open");
|
|
159
163
|
|
|
160
164
|
// Run async operations in background
|
|
161
165
|
(async () => {
|
|
162
166
|
try {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
// Save socket
|
|
168
|
-
const connGlobalState =
|
|
169
|
-
actorDriver.getGenericConnGlobalState(actorId);
|
|
170
|
-
connGlobalState.websockets.set(connId, ws);
|
|
167
|
+
let conn: AnyConn;
|
|
168
|
+
|
|
169
|
+
// Create or reconnect connection
|
|
171
170
|
actor.rLog.debug({
|
|
172
|
-
msg:
|
|
171
|
+
msg: connId
|
|
172
|
+
? "websocket reconnection attempt"
|
|
173
|
+
: "new websocket connection",
|
|
174
|
+
connId,
|
|
173
175
|
actorId,
|
|
174
|
-
totalCount: connGlobalState.websockets.size,
|
|
175
176
|
});
|
|
176
177
|
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
conn = await actor.createConn(
|
|
179
|
+
{
|
|
180
|
+
socketId,
|
|
181
|
+
driverState: {
|
|
182
|
+
[ConnDriverKind.WEBSOCKET]: {
|
|
183
|
+
encoding,
|
|
184
|
+
websocket: ws,
|
|
185
|
+
closePromise,
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
parameters,
|
|
190
|
+
req,
|
|
179
191
|
connId,
|
|
180
192
|
connToken,
|
|
181
|
-
parameters,
|
|
182
|
-
connState,
|
|
183
|
-
CONNECTION_DRIVER_WEBSOCKET,
|
|
184
|
-
{ encoding } satisfies GenericWebSocketDriverState,
|
|
185
|
-
authData,
|
|
186
193
|
);
|
|
187
194
|
|
|
188
195
|
// Unblock other handlers
|
|
189
|
-
handlersResolve({ conn, actor, connId });
|
|
196
|
+
handlersResolve({ conn, actor, connId: conn.id });
|
|
190
197
|
} catch (error) {
|
|
191
198
|
handlersReject(error);
|
|
192
199
|
|
|
@@ -258,6 +265,10 @@ export async function handleWebSocketConnect(
|
|
|
258
265
|
},
|
|
259
266
|
ws: WSContext,
|
|
260
267
|
) => {
|
|
268
|
+
handlersReject(`WebSocket closed (${event.code}): ${event.reason}`);
|
|
269
|
+
|
|
270
|
+
closePromise.resolve();
|
|
271
|
+
|
|
261
272
|
if (event.wasClean) {
|
|
262
273
|
actor.rLog.info({
|
|
263
274
|
msg: "websocket closed",
|
|
@@ -280,24 +291,8 @@ export async function handleWebSocketConnect(
|
|
|
280
291
|
|
|
281
292
|
// Handle cleanup asynchronously
|
|
282
293
|
handlersPromise
|
|
283
|
-
.then(({ conn, actor
|
|
284
|
-
|
|
285
|
-
actorDriver.getGenericConnGlobalState(actorId);
|
|
286
|
-
const didDelete = connGlobalState.websockets.delete(connId);
|
|
287
|
-
if (didDelete) {
|
|
288
|
-
actor.rLog.info({
|
|
289
|
-
msg: "removing websocket for conn",
|
|
290
|
-
totalCount: connGlobalState.websockets.size,
|
|
291
|
-
});
|
|
292
|
-
} else {
|
|
293
|
-
actor.rLog.warn({
|
|
294
|
-
msg: "websocket does not exist for conn",
|
|
295
|
-
actorId,
|
|
296
|
-
totalCount: connGlobalState.websockets.size,
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
actor.__removeConn(conn);
|
|
294
|
+
.then(({ conn, actor }) => {
|
|
295
|
+
actor.__connDisconnected(conn, event.wasClean, socketId);
|
|
301
296
|
})
|
|
302
297
|
.catch((error) => {
|
|
303
298
|
deconstructError(
|
|
@@ -332,46 +327,50 @@ export async function handleSseConnect(
|
|
|
332
327
|
_runConfig: RunConfig,
|
|
333
328
|
actorDriver: ActorDriver,
|
|
334
329
|
actorId: string,
|
|
335
|
-
authData: unknown,
|
|
336
330
|
) {
|
|
331
|
+
c.header("Content-Encoding", "Identity");
|
|
332
|
+
|
|
337
333
|
const encoding = getRequestEncoding(c.req);
|
|
338
334
|
const parameters = getRequestConnParams(c.req);
|
|
335
|
+
const socketId = generateConnSocketId();
|
|
336
|
+
|
|
337
|
+
// Check for reconnection parameters
|
|
338
|
+
const connId = c.req.header(HEADER_CONN_ID);
|
|
339
|
+
const connToken = c.req.header(HEADER_CONN_TOKEN);
|
|
339
340
|
|
|
340
341
|
// Return the main handler with all async work inside
|
|
341
342
|
return streamSSE(c, async (stream) => {
|
|
342
343
|
let actor: AnyActorInstance | undefined;
|
|
343
|
-
let connId: string | undefined;
|
|
344
|
-
let connToken: string | undefined;
|
|
345
|
-
let connState: unknown;
|
|
346
344
|
let conn: AnyConn | undefined;
|
|
347
345
|
|
|
348
346
|
try {
|
|
349
347
|
// Do all async work inside the handler
|
|
350
348
|
actor = await actorDriver.loadActor(actorId);
|
|
351
|
-
connId = generateConnId();
|
|
352
|
-
connToken = generateConnToken();
|
|
353
|
-
connState = await actor.prepareConn(parameters, c.req.raw);
|
|
354
349
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
.sseStreams.set(connId, stream);
|
|
350
|
+
// Create or reconnect connection
|
|
351
|
+
actor.rLog.debug({
|
|
352
|
+
msg: connId ? "sse reconnection attempt" : "sse open",
|
|
353
|
+
connId,
|
|
354
|
+
});
|
|
361
355
|
|
|
362
|
-
// Create connection
|
|
363
356
|
conn = await actor.createConn(
|
|
357
|
+
{
|
|
358
|
+
socketId,
|
|
359
|
+
driverState: {
|
|
360
|
+
[ConnDriverKind.SSE]: {
|
|
361
|
+
encoding,
|
|
362
|
+
stream: stream,
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
parameters,
|
|
367
|
+
c.req.raw,
|
|
364
368
|
connId,
|
|
365
369
|
connToken,
|
|
366
|
-
parameters,
|
|
367
|
-
connState,
|
|
368
|
-
CONNECTION_DRIVER_SSE,
|
|
369
|
-
{ encoding } satisfies GenericSseDriverState,
|
|
370
|
-
authData,
|
|
371
370
|
);
|
|
372
371
|
|
|
373
372
|
// Wait for close
|
|
374
|
-
const abortResolver =
|
|
373
|
+
const abortResolver = promiseWithResolvers();
|
|
375
374
|
|
|
376
375
|
// HACK: This is required so the abort handler below works
|
|
377
376
|
//
|
|
@@ -380,18 +379,14 @@ export async function handleSseConnect(
|
|
|
380
379
|
|
|
381
380
|
// Handle stream abort (when client closes the connection)
|
|
382
381
|
c.req.raw.signal.addEventListener("abort", async () => {
|
|
383
|
-
|
|
382
|
+
invariant(actor, "actor should exist");
|
|
383
|
+
const rLog = actor.rLog ?? loggerWithoutContext();
|
|
384
384
|
try {
|
|
385
385
|
rLog.debug("sse stream aborted");
|
|
386
386
|
|
|
387
387
|
// Cleanup
|
|
388
|
-
if (
|
|
389
|
-
|
|
390
|
-
.getGenericConnGlobalState(actorId)
|
|
391
|
-
.sseStreams.delete(connId);
|
|
392
|
-
}
|
|
393
|
-
if (conn && actor) {
|
|
394
|
-
actor.__removeConn(conn);
|
|
388
|
+
if (conn) {
|
|
389
|
+
actor.__connDisconnected(conn, false, socketId);
|
|
395
390
|
}
|
|
396
391
|
|
|
397
392
|
abortResolver.resolve(undefined);
|
|
@@ -401,24 +396,33 @@ export async function handleSseConnect(
|
|
|
401
396
|
}
|
|
402
397
|
});
|
|
403
398
|
|
|
404
|
-
// HACK: Will throw if not configured
|
|
405
|
-
try {
|
|
406
|
-
|
|
407
|
-
} catch {}
|
|
399
|
+
// // HACK: Will throw if not configured
|
|
400
|
+
// try {
|
|
401
|
+
// c.executionCtx.waitUntil(abortResolver.promise);
|
|
402
|
+
// } catch {}
|
|
403
|
+
|
|
404
|
+
// Send ping every second to keep the connection alive
|
|
405
|
+
//
|
|
406
|
+
// NOTE: This is required on Cloudflare Workers in order to detect when the connection is closed
|
|
407
|
+
while (true) {
|
|
408
|
+
if (stream.closed || stream.aborted) {
|
|
409
|
+
actor?.rLog.debug({
|
|
410
|
+
msg: "sse stream closed",
|
|
411
|
+
closed: stream.closed,
|
|
412
|
+
aborted: stream.aborted,
|
|
413
|
+
});
|
|
414
|
+
break;
|
|
415
|
+
}
|
|
408
416
|
|
|
409
|
-
|
|
410
|
-
|
|
417
|
+
await stream.writeSSE({ event: "ping", data: "" });
|
|
418
|
+
await stream.sleep(SSE_PING_INTERVAL);
|
|
419
|
+
}
|
|
411
420
|
} catch (error) {
|
|
412
421
|
loggerWithoutContext().error({ msg: "error in sse connection", error });
|
|
413
422
|
|
|
414
423
|
// Cleanup on error
|
|
415
|
-
if (connId !== undefined) {
|
|
416
|
-
actorDriver
|
|
417
|
-
.getGenericConnGlobalState(actorId)
|
|
418
|
-
.sseStreams.delete(connId);
|
|
419
|
-
}
|
|
420
424
|
if (conn && actor !== undefined) {
|
|
421
|
-
actor.
|
|
425
|
+
actor.__connDisconnected(conn, false, socketId);
|
|
422
426
|
}
|
|
423
427
|
|
|
424
428
|
// Close the stream on error
|
|
@@ -436,7 +440,6 @@ export async function handleAction(
|
|
|
436
440
|
actorDriver: ActorDriver,
|
|
437
441
|
actionName: string,
|
|
438
442
|
actorId: string,
|
|
439
|
-
authData: unknown,
|
|
440
443
|
) {
|
|
441
444
|
const encoding = getRequestEncoding(c.req);
|
|
442
445
|
const parameters = getRequestConnParams(c.req);
|
|
@@ -449,6 +452,7 @@ export async function handleAction(
|
|
|
449
452
|
HTTP_ACTION_REQUEST_VERSIONED,
|
|
450
453
|
);
|
|
451
454
|
const actionArgs = cbor.decode(new Uint8Array(request.args));
|
|
455
|
+
const socketId = generateConnSocketId();
|
|
452
456
|
|
|
453
457
|
// Invoke the action
|
|
454
458
|
let actor: AnyActorInstance | undefined;
|
|
@@ -460,15 +464,13 @@ export async function handleAction(
|
|
|
460
464
|
actor.rLog.debug({ msg: "handling action", actionName, encoding });
|
|
461
465
|
|
|
462
466
|
// Create conn
|
|
463
|
-
const connState = await actor.prepareConn(parameters, c.req.raw);
|
|
464
467
|
conn = await actor.createConn(
|
|
465
|
-
|
|
466
|
-
|
|
468
|
+
{
|
|
469
|
+
socketId,
|
|
470
|
+
driverState: { [ConnDriverKind.HTTP]: {} },
|
|
471
|
+
},
|
|
467
472
|
parameters,
|
|
468
|
-
|
|
469
|
-
CONNECTION_DRIVER_HTTP,
|
|
470
|
-
{} satisfies GenericHttpDriverState,
|
|
471
|
-
authData,
|
|
473
|
+
c.req.raw,
|
|
472
474
|
);
|
|
473
475
|
|
|
474
476
|
// Call action
|
|
@@ -476,7 +478,8 @@ export async function handleAction(
|
|
|
476
478
|
output = await actor.executeAction(ctx, actionName, actionArgs);
|
|
477
479
|
} finally {
|
|
478
480
|
if (conn) {
|
|
479
|
-
|
|
481
|
+
// HTTP connections don't have persistent sockets, so no socket ID needed
|
|
482
|
+
actor?.__connDisconnected(conn, true, socketId);
|
|
480
483
|
}
|
|
481
484
|
}
|
|
482
485
|
|
|
@@ -489,7 +492,9 @@ export async function handleAction(
|
|
|
489
492
|
responseData,
|
|
490
493
|
HTTP_ACTION_RESPONSE_VERSIONED,
|
|
491
494
|
);
|
|
492
|
-
|
|
495
|
+
|
|
496
|
+
// TODO: Remvoe any, Hono is being a dumbass
|
|
497
|
+
return c.body(serialized as Uint8Array as any, 200, {
|
|
493
498
|
"Content-Type": contentTypeForEncoding(encoding),
|
|
494
499
|
});
|
|
495
500
|
}
|
|
@@ -534,12 +539,48 @@ export async function handleConnectionMessage(
|
|
|
534
539
|
return c.json({});
|
|
535
540
|
}
|
|
536
541
|
|
|
542
|
+
export async function handleConnectionClose(
|
|
543
|
+
c: HonoContext,
|
|
544
|
+
_runConfig: RunConfig,
|
|
545
|
+
actorDriver: ActorDriver,
|
|
546
|
+
connId: string,
|
|
547
|
+
connToken: string,
|
|
548
|
+
actorId: string,
|
|
549
|
+
) {
|
|
550
|
+
const actor = await actorDriver.loadActor(actorId);
|
|
551
|
+
|
|
552
|
+
// Find connection
|
|
553
|
+
const conn = actor.conns.get(connId);
|
|
554
|
+
if (!conn) {
|
|
555
|
+
throw new errors.ConnNotFound(connId);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Authenticate connection
|
|
559
|
+
if (conn._token !== connToken) {
|
|
560
|
+
throw new errors.IncorrectConnToken();
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// Check if this is an SSE connection
|
|
564
|
+
if (
|
|
565
|
+
!conn.__socket?.driverState ||
|
|
566
|
+
!(ConnDriverKind.SSE in conn.__socket.driverState)
|
|
567
|
+
) {
|
|
568
|
+
throw new errors.UserError(
|
|
569
|
+
"Connection close is only supported for SSE connections",
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// Close the SSE connection
|
|
574
|
+
await conn.disconnect("Connection closed by client request");
|
|
575
|
+
|
|
576
|
+
return c.json({});
|
|
577
|
+
}
|
|
578
|
+
|
|
537
579
|
export async function handleRawWebSocketHandler(
|
|
538
580
|
req: Request | undefined,
|
|
539
581
|
path: string,
|
|
540
582
|
actorDriver: ActorDriver,
|
|
541
583
|
actorId: string,
|
|
542
|
-
authData: unknown,
|
|
543
584
|
): Promise<UpgradeWebSocketArgs> {
|
|
544
585
|
const actor = await actorDriver.loadActor(actorId);
|
|
545
586
|
|
|
@@ -644,38 +685,6 @@ export function getRequestQuery(c: HonoContext): unknown {
|
|
|
644
685
|
}
|
|
645
686
|
}
|
|
646
687
|
|
|
647
|
-
export const HEADER_ACTOR_QUERY = "X-RivetKit-Query";
|
|
648
|
-
|
|
649
|
-
export const HEADER_ENCODING = "X-RivetKit-Encoding";
|
|
650
|
-
|
|
651
|
-
// IMPORTANT: Params must be in headers or in an E2EE part of the request (i.e. NOT the URL or query string) in order to ensure that tokens can be securely passed in params.
|
|
652
|
-
export const HEADER_CONN_PARAMS = "X-RivetKit-Conn-Params";
|
|
653
|
-
|
|
654
|
-
// Internal header
|
|
655
|
-
export const HEADER_AUTH_DATA = "X-RivetKit-Auth-Data";
|
|
656
|
-
|
|
657
|
-
export const HEADER_ACTOR_ID = "X-RivetKit-Actor";
|
|
658
|
-
|
|
659
|
-
export const HEADER_CONN_ID = "X-RivetKit-Conn";
|
|
660
|
-
|
|
661
|
-
export const HEADER_CONN_TOKEN = "X-RivetKit-Conn-Token";
|
|
662
|
-
|
|
663
|
-
/**
|
|
664
|
-
* Headers that publics can send from public clients.
|
|
665
|
-
*
|
|
666
|
-
* Used for CORS.
|
|
667
|
-
**/
|
|
668
|
-
export const ALLOWED_PUBLIC_HEADERS = [
|
|
669
|
-
"Content-Type",
|
|
670
|
-
"User-Agent",
|
|
671
|
-
HEADER_ACTOR_QUERY,
|
|
672
|
-
HEADER_ENCODING,
|
|
673
|
-
HEADER_CONN_PARAMS,
|
|
674
|
-
HEADER_ACTOR_ID,
|
|
675
|
-
HEADER_CONN_ID,
|
|
676
|
-
HEADER_CONN_TOKEN,
|
|
677
|
-
];
|
|
678
|
-
|
|
679
688
|
// Helper to get connection parameters for the request
|
|
680
689
|
export function getRequestConnParams(req: HonoRequest): unknown {
|
|
681
690
|
const paramsParam = req.header(HEADER_CONN_PARAMS);
|