rivetkit 2.0.7 → 2.0.9
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/tsup/{chunk-OSK2VSJF.cjs → chunk-2MJYYF2Q.cjs} +12 -12
- package/dist/tsup/{chunk-OSK2VSJF.cjs.map → chunk-2MJYYF2Q.cjs.map} +1 -1
- package/dist/tsup/{chunk-NUA6LOOJ.cjs → chunk-4PSLOAXR.cjs} +216 -204
- package/dist/tsup/chunk-4PSLOAXR.cjs.map +1 -0
- package/dist/tsup/{chunk-F7YL5G7Q.cjs → chunk-4YV6RDZL.cjs} +255 -229
- package/dist/tsup/chunk-4YV6RDZL.cjs.map +1 -0
- package/dist/tsup/{chunk-3ALZ7EGX.cjs → chunk-7OMMIAWP.cjs} +11 -11
- package/dist/tsup/{chunk-3ALZ7EGX.cjs.map → chunk-7OMMIAWP.cjs.map} +1 -1
- package/dist/tsup/{chunk-GWJTWY3G.cjs → chunk-A44TWAS5.cjs} +6 -6
- package/dist/tsup/{chunk-GWJTWY3G.cjs.map → chunk-A44TWAS5.cjs.map} +1 -1
- package/dist/tsup/{chunk-B6N6VM37.js → chunk-APHV6WXU.js} +2 -2
- package/dist/tsup/{chunk-ETDWYT2P.cjs → chunk-DL7TPF63.cjs} +7 -7
- package/dist/tsup/{chunk-ETDWYT2P.cjs.map → chunk-DL7TPF63.cjs.map} +1 -1
- package/dist/tsup/{chunk-YL4VZMMT.js → chunk-DLPIL3VC.js} +2 -2
- package/dist/tsup/{chunk-VAF63BEI.cjs → chunk-DZZQG7VH.cjs} +3 -3
- package/dist/tsup/{chunk-VAF63BEI.cjs.map → chunk-DZZQG7VH.cjs.map} +1 -1
- package/dist/tsup/{chunk-RLBM6D4L.js → chunk-E63WU5PL.js} +3 -3
- package/dist/tsup/chunk-E63WU5PL.js.map +1 -0
- package/dist/tsup/{chunk-DIHKN7NM.js → chunk-F2YZNUPU.js} +3 -3
- package/dist/tsup/{chunk-KHRZPP5T.js → chunk-FZP2IBIX.js} +94 -68
- package/dist/tsup/chunk-FZP2IBIX.js.map +1 -0
- package/dist/tsup/{chunk-NII4KKHD.js → chunk-KHZ2QSQ4.js} +28 -16
- package/dist/tsup/chunk-KHZ2QSQ4.js.map +1 -0
- package/dist/tsup/{chunk-4EXJ4ITR.cjs → chunk-QGRYH6TU.cjs} +3 -3
- package/dist/tsup/{chunk-4EXJ4ITR.cjs.map → chunk-QGRYH6TU.cjs.map} +1 -1
- package/dist/tsup/{chunk-NRELKXIX.js → chunk-R7OP5N25.js} +56 -46
- package/dist/tsup/chunk-R7OP5N25.js.map +1 -0
- package/dist/tsup/{chunk-NDCVQZBS.cjs → chunk-SDXTJDDR.cjs} +62 -52
- package/dist/tsup/chunk-SDXTJDDR.cjs.map +1 -0
- package/dist/tsup/{chunk-7OOBMCQI.cjs → chunk-SOC4HWCG.cjs} +23 -22
- package/dist/tsup/chunk-SOC4HWCG.cjs.map +1 -0
- package/dist/tsup/{chunk-LXAVET4A.cjs → chunk-U2IXX6DY.cjs} +3 -3
- package/dist/tsup/{chunk-LXAVET4A.cjs.map → chunk-U2IXX6DY.cjs.map} +1 -1
- package/dist/tsup/{chunk-2NL3KGJ7.js → chunk-VVCL5DXN.js} +5 -4
- package/dist/tsup/chunk-VVCL5DXN.js.map +1 -0
- package/dist/tsup/{chunk-54MAHBLL.js → chunk-WBSPHV5V.js} +2 -2
- package/dist/tsup/{chunk-WAT5AE7S.js → chunk-WRSWUDFA.js} +5 -5
- package/dist/tsup/{chunk-PD6HCAJE.js → chunk-YR2VY4XS.js} +2 -2
- package/dist/tsup/client/mod.cjs +9 -9
- package/dist/tsup/client/mod.d.cts +2 -2
- package/dist/tsup/client/mod.d.ts +2 -2
- 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/{conn-DCSQgIlw.d.ts → conn-Bt8rkUzm.d.ts} +19 -1
- package/dist/tsup/{conn-DdzHTm2E.d.cts → conn-CEh3WKbA.d.cts} +19 -1
- package/dist/tsup/driver-helpers/mod.cjs +7 -5
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -1
- package/dist/tsup/driver-helpers/mod.d.cts +4 -2
- package/dist/tsup/driver-helpers/mod.d.ts +4 -2
- package/dist/tsup/driver-helpers/mod.js +7 -5
- package/dist/tsup/driver-test-suite/mod.cjs +103 -113
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/driver-test-suite/mod.d.cts +3 -1
- package/dist/tsup/driver-test-suite/mod.d.ts +3 -1
- package/dist/tsup/driver-test-suite/mod.js +45 -55
- package/dist/tsup/driver-test-suite/mod.js.map +1 -1
- package/dist/tsup/inspector/mod.cjs +6 -6
- package/dist/tsup/inspector/mod.d.cts +2 -2
- package/dist/tsup/inspector/mod.d.ts +2 -2
- package/dist/tsup/inspector/mod.js +5 -5
- package/dist/tsup/mod.cjs +10 -10
- package/dist/tsup/mod.d.cts +5 -5
- package/dist/tsup/mod.d.ts +5 -5
- package/dist/tsup/mod.js +9 -9
- package/dist/tsup/test/mod.cjs +11 -11
- package/dist/tsup/test/mod.d.cts +1 -1
- package/dist/tsup/test/mod.d.ts +1 -1
- package/dist/tsup/test/mod.js +10 -10
- package/dist/tsup/utils.cjs +2 -2
- package/dist/tsup/utils.js +1 -1
- package/package.json +2 -2
- package/src/actor/instance.ts +20 -7
- package/src/actor/router-endpoints.ts +2 -1
- package/src/actor/router.ts +27 -24
- package/src/client/actor-conn.ts +5 -1
- package/src/client/config.ts +2 -0
- package/src/driver-helpers/mod.ts +1 -0
- package/src/driver-test-suite/mod.ts +11 -2
- package/src/driver-test-suite/tests/actor-schedule.ts +14 -37
- package/src/driver-test-suite/tests/actor-sleep.ts +18 -18
- package/src/drivers/engine/actor-driver.ts +39 -10
- package/src/drivers/file-system/manager.ts +5 -1
- package/src/manager/driver.ts +1 -1
- package/src/manager/router.ts +49 -41
- package/src/registry/mod.ts +11 -2
- package/src/remote-manager-driver/mod.ts +3 -2
- package/src/serde.ts +15 -0
- package/dist/tsup/chunk-2NL3KGJ7.js.map +0 -1
- package/dist/tsup/chunk-7OOBMCQI.cjs.map +0 -1
- package/dist/tsup/chunk-F7YL5G7Q.cjs.map +0 -1
- package/dist/tsup/chunk-KHRZPP5T.js.map +0 -1
- package/dist/tsup/chunk-NDCVQZBS.cjs.map +0 -1
- package/dist/tsup/chunk-NII4KKHD.js.map +0 -1
- package/dist/tsup/chunk-NRELKXIX.js.map +0 -1
- package/dist/tsup/chunk-NUA6LOOJ.cjs.map +0 -1
- package/dist/tsup/chunk-RLBM6D4L.js.map +0 -1
- /package/dist/tsup/{chunk-B6N6VM37.js.map → chunk-APHV6WXU.js.map} +0 -0
- /package/dist/tsup/{chunk-YL4VZMMT.js.map → chunk-DLPIL3VC.js.map} +0 -0
- /package/dist/tsup/{chunk-DIHKN7NM.js.map → chunk-F2YZNUPU.js.map} +0 -0
- /package/dist/tsup/{chunk-54MAHBLL.js.map → chunk-WBSPHV5V.js.map} +0 -0
- /package/dist/tsup/{chunk-WAT5AE7S.js.map → chunk-WRSWUDFA.js.map} +0 -0
- /package/dist/tsup/{chunk-PD6HCAJE.js.map → chunk-YR2VY4XS.js.map} +0 -0
|
@@ -6,6 +6,8 @@ export function runActorScheduleTests(driverTestConfig: DriverTestConfig) {
|
|
|
6
6
|
describe.skipIf(driverTestConfig.skip?.schedule)(
|
|
7
7
|
"Actor Schedule Tests",
|
|
8
8
|
() => {
|
|
9
|
+
// See alarm + actor sleeping test in actor-sleep.ts
|
|
10
|
+
|
|
9
11
|
describe("Scheduled Alarms", () => {
|
|
10
12
|
test("executes c.schedule.at() with specific timestamp", async (c) => {
|
|
11
13
|
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
@@ -13,12 +15,12 @@ export function runActorScheduleTests(driverTestConfig: DriverTestConfig) {
|
|
|
13
15
|
// Create instance
|
|
14
16
|
const scheduled = client.scheduled.getOrCreate();
|
|
15
17
|
|
|
16
|
-
// Schedule a task to run
|
|
17
|
-
const timestamp = Date.now() +
|
|
18
|
+
// Schedule a task to run using timestamp
|
|
19
|
+
const timestamp = Date.now() + 250;
|
|
18
20
|
await scheduled.scheduleTaskAt(timestamp);
|
|
19
21
|
|
|
20
22
|
// Wait for longer than the scheduled time
|
|
21
|
-
await waitFor(driverTestConfig,
|
|
23
|
+
await waitFor(driverTestConfig, 500);
|
|
22
24
|
|
|
23
25
|
// Verify the scheduled task ran
|
|
24
26
|
const lastRun = await scheduled.getLastRun();
|
|
@@ -34,11 +36,11 @@ export function runActorScheduleTests(driverTestConfig: DriverTestConfig) {
|
|
|
34
36
|
// Create instance
|
|
35
37
|
const scheduled = client.scheduled.getOrCreate();
|
|
36
38
|
|
|
37
|
-
// Schedule a task to run
|
|
38
|
-
await scheduled.scheduleTaskAfter(
|
|
39
|
+
// Schedule a task to run using delay
|
|
40
|
+
await scheduled.scheduleTaskAfter(250);
|
|
39
41
|
|
|
40
42
|
// Wait for longer than the scheduled time
|
|
41
|
-
await waitFor(driverTestConfig,
|
|
43
|
+
await waitFor(driverTestConfig, 500);
|
|
42
44
|
|
|
43
45
|
// Verify the scheduled task ran
|
|
44
46
|
const lastRun = await scheduled.getLastRun();
|
|
@@ -48,31 +50,6 @@ export function runActorScheduleTests(driverTestConfig: DriverTestConfig) {
|
|
|
48
50
|
expect(scheduledCount).toBe(1);
|
|
49
51
|
});
|
|
50
52
|
|
|
51
|
-
test("scheduled tasks persist across actor restarts", async (c) => {
|
|
52
|
-
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
53
|
-
|
|
54
|
-
// Create instance and schedule
|
|
55
|
-
const scheduled = client.scheduled.getOrCreate();
|
|
56
|
-
await scheduled.scheduleTaskAfter(200);
|
|
57
|
-
|
|
58
|
-
// Wait a little so the schedule is stored but hasn't triggered yet
|
|
59
|
-
await waitFor(driverTestConfig, 100);
|
|
60
|
-
|
|
61
|
-
// Get a new reference to simulate actor restart
|
|
62
|
-
const newInstance = client.scheduled.getOrCreate();
|
|
63
|
-
|
|
64
|
-
// Verify the schedule still exists but hasn't run yet
|
|
65
|
-
const initialCount = await newInstance.getScheduledCount();
|
|
66
|
-
expect(initialCount).toBe(0);
|
|
67
|
-
|
|
68
|
-
// Wait for the scheduled task to execute
|
|
69
|
-
await waitFor(driverTestConfig, 200);
|
|
70
|
-
|
|
71
|
-
// Verify the scheduled task ran after "restart"
|
|
72
|
-
const scheduledCount = await newInstance.getScheduledCount();
|
|
73
|
-
expect(scheduledCount).toBe(1);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
53
|
test("multiple scheduled tasks execute in order", async (c) => {
|
|
77
54
|
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
78
55
|
|
|
@@ -83,22 +60,22 @@ export function runActorScheduleTests(driverTestConfig: DriverTestConfig) {
|
|
|
83
60
|
await scheduled.clearHistory();
|
|
84
61
|
|
|
85
62
|
// Schedule multiple tasks with different delays
|
|
86
|
-
await scheduled.scheduleTaskAfterWithId("first",
|
|
87
|
-
await scheduled.scheduleTaskAfterWithId("second",
|
|
88
|
-
await scheduled.scheduleTaskAfterWithId("third",
|
|
63
|
+
await scheduled.scheduleTaskAfterWithId("first", 250);
|
|
64
|
+
await scheduled.scheduleTaskAfterWithId("second", 750);
|
|
65
|
+
await scheduled.scheduleTaskAfterWithId("third", 1250);
|
|
89
66
|
|
|
90
67
|
// Wait for first task only
|
|
91
|
-
await waitFor(driverTestConfig,
|
|
68
|
+
await waitFor(driverTestConfig, 500);
|
|
92
69
|
const history1 = await scheduled.getTaskHistory();
|
|
93
70
|
expect(history1).toEqual(["first"]);
|
|
94
71
|
|
|
95
72
|
// Wait for second task
|
|
96
|
-
await waitFor(driverTestConfig,
|
|
73
|
+
await waitFor(driverTestConfig, 500);
|
|
97
74
|
const history2 = await scheduled.getTaskHistory();
|
|
98
75
|
expect(history2).toEqual(["first", "second"]);
|
|
99
76
|
|
|
100
77
|
// Wait for third task
|
|
101
|
-
await waitFor(driverTestConfig,
|
|
78
|
+
await waitFor(driverTestConfig, 500);
|
|
102
79
|
const history3 = await scheduled.getTaskHistory();
|
|
103
80
|
expect(history3).toEqual(["first", "second", "third"]);
|
|
104
81
|
});
|
|
@@ -29,7 +29,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
29
29
|
await sleepActor.triggerSleep();
|
|
30
30
|
|
|
31
31
|
// HACK: Wait for sleep to finish in background
|
|
32
|
-
await waitFor(driverTestConfig,
|
|
32
|
+
await waitFor(driverTestConfig, 250);
|
|
33
33
|
|
|
34
34
|
// Get sleep count after restore
|
|
35
35
|
{
|
|
@@ -59,7 +59,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
59
59
|
await sleepActor.dispose();
|
|
60
60
|
|
|
61
61
|
// HACK: Wait for sleep to finish in background
|
|
62
|
-
await waitFor(driverTestConfig,
|
|
62
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250);
|
|
63
63
|
|
|
64
64
|
// Reconnect to get sleep count after restore
|
|
65
65
|
const sleepActor2 = client.sleep.getOrCreate();
|
|
@@ -84,7 +84,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
// Wait for sleep
|
|
87
|
-
await waitFor(driverTestConfig, SLEEP_TIMEOUT +
|
|
87
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250);
|
|
88
88
|
|
|
89
89
|
// Get sleep count after restore
|
|
90
90
|
{
|
|
@@ -111,7 +111,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
111
111
|
await sleepActor.dispose();
|
|
112
112
|
|
|
113
113
|
// Wait for sleep
|
|
114
|
-
await waitFor(driverTestConfig, SLEEP_TIMEOUT +
|
|
114
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250);
|
|
115
115
|
|
|
116
116
|
// Reconnect to get sleep count after restore
|
|
117
117
|
const sleepActor2 = client.sleep.getOrCreate();
|
|
@@ -136,7 +136,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
// Wait almost until sleep timeout, then make RPC call
|
|
139
|
-
await waitFor(driverTestConfig, SLEEP_TIMEOUT -
|
|
139
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT - 250);
|
|
140
140
|
|
|
141
141
|
// RPC call should reset the sleep timer
|
|
142
142
|
{
|
|
@@ -146,7 +146,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
// Wait another partial timeout period - actor should still be awake
|
|
149
|
-
await waitFor(driverTestConfig, SLEEP_TIMEOUT -
|
|
149
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT - 250);
|
|
150
150
|
|
|
151
151
|
// Actor should still be awake
|
|
152
152
|
{
|
|
@@ -156,7 +156,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
// Now wait for full timeout without any RPC calls
|
|
159
|
-
await waitFor(driverTestConfig, SLEEP_TIMEOUT +
|
|
159
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250);
|
|
160
160
|
|
|
161
161
|
// Actor should have slept and restarted
|
|
162
162
|
{
|
|
@@ -180,10 +180,10 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
// Set an alarm to keep the actor awake
|
|
183
|
-
await sleepActor.setAlarm(SLEEP_TIMEOUT -
|
|
183
|
+
await sleepActor.setAlarm(SLEEP_TIMEOUT - 250);
|
|
184
184
|
|
|
185
185
|
// Wait until after SLEEPT_IMEOUT to validate the actor did not sleep
|
|
186
|
-
await waitFor(driverTestConfig, SLEEP_TIMEOUT +
|
|
186
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250);
|
|
187
187
|
|
|
188
188
|
// Actor should not have slept
|
|
189
189
|
{
|
|
@@ -207,7 +207,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
// Set an alarm to keep the actor awake
|
|
210
|
-
await sleepActor.setAlarm(SLEEP_TIMEOUT +
|
|
210
|
+
await sleepActor.setAlarm(SLEEP_TIMEOUT + 250);
|
|
211
211
|
|
|
212
212
|
// Wait until after SLEEPT_IMEOUT to validate the actor did not sleep
|
|
213
213
|
await waitFor(driverTestConfig, SLEEP_TIMEOUT + 200);
|
|
@@ -239,7 +239,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
239
239
|
);
|
|
240
240
|
const longRunningPromise = sleepActor.longRunningRpc();
|
|
241
241
|
await waitPromise;
|
|
242
|
-
await waitFor(driverTestConfig, SLEEP_TIMEOUT +
|
|
242
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250);
|
|
243
243
|
await sleepActor.finishLongRunningRpc();
|
|
244
244
|
await longRunningPromise;
|
|
245
245
|
|
|
@@ -252,7 +252,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
252
252
|
await sleepActor.dispose();
|
|
253
253
|
|
|
254
254
|
// Now wait for the sleep timeout
|
|
255
|
-
await waitFor(driverTestConfig, SLEEP_TIMEOUT +
|
|
255
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250);
|
|
256
256
|
|
|
257
257
|
// Actor should have slept after the timeout
|
|
258
258
|
const sleepActor2 = client.sleepWithLongRpc.getOrCreate();
|
|
@@ -298,7 +298,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
298
298
|
});
|
|
299
299
|
|
|
300
300
|
// Wait longer than sleep timeout while keeping WebSocket connected
|
|
301
|
-
await waitFor(driverTestConfig, SLEEP_TIMEOUT +
|
|
301
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250);
|
|
302
302
|
|
|
303
303
|
// Send a message to check if actor is still alive
|
|
304
304
|
ws.send(JSON.stringify({ type: "getCounts" }));
|
|
@@ -320,7 +320,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
320
320
|
ws.close();
|
|
321
321
|
|
|
322
322
|
// Wait for sleep timeout after WebSocket closed
|
|
323
|
-
await waitFor(driverTestConfig, SLEEP_TIMEOUT +
|
|
323
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250);
|
|
324
324
|
|
|
325
325
|
// Actor should have slept after WebSocket closed
|
|
326
326
|
{
|
|
@@ -347,7 +347,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
347
347
|
}
|
|
348
348
|
|
|
349
349
|
// Start a long-running fetch request
|
|
350
|
-
const fetchDuration = SLEEP_TIMEOUT +
|
|
350
|
+
const fetchDuration = SLEEP_TIMEOUT + 250;
|
|
351
351
|
const fetchPromise = sleepActor.fetch(
|
|
352
352
|
`long-request?duration=${fetchDuration}`,
|
|
353
353
|
);
|
|
@@ -365,7 +365,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
365
365
|
}
|
|
366
366
|
|
|
367
367
|
// Wait for sleep timeout
|
|
368
|
-
await waitFor(driverTestConfig, SLEEP_TIMEOUT +
|
|
368
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250);
|
|
369
369
|
|
|
370
370
|
// Actor should have slept after timeout
|
|
371
371
|
{
|
|
@@ -389,7 +389,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
389
389
|
}
|
|
390
390
|
|
|
391
391
|
// Wait longer than sleep timeout
|
|
392
|
-
await waitFor(driverTestConfig, SLEEP_TIMEOUT +
|
|
392
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250);
|
|
393
393
|
|
|
394
394
|
// Actor should NOT have slept due to noSleep option
|
|
395
395
|
{
|
|
@@ -399,7 +399,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
|
|
|
399
399
|
}
|
|
400
400
|
|
|
401
401
|
// Wait even longer to be sure
|
|
402
|
-
await waitFor(driverTestConfig, SLEEP_TIMEOUT +
|
|
402
|
+
await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250);
|
|
403
403
|
|
|
404
404
|
// Actor should still not have slept
|
|
405
405
|
{
|
|
@@ -35,7 +35,11 @@ import {
|
|
|
35
35
|
} from "@/driver-helpers/mod";
|
|
36
36
|
import type { RegistryConfig } from "@/registry/config";
|
|
37
37
|
import type { RunConfig } from "@/registry/run-config";
|
|
38
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
type LongTimeoutHandle,
|
|
40
|
+
promiseWithResolvers,
|
|
41
|
+
setLongTimeout,
|
|
42
|
+
} from "@/utils";
|
|
39
43
|
import type { Config } from "./config";
|
|
40
44
|
import { KEYS } from "./kv";
|
|
41
45
|
import { logger } from "./log";
|
|
@@ -58,6 +62,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
58
62
|
#actors: Map<string, ActorHandler> = new Map();
|
|
59
63
|
#actorRouter: ActorRouter;
|
|
60
64
|
#version: number = 1; // Version for the runner protocol
|
|
65
|
+
#alarmTimeout?: LongTimeoutHandle;
|
|
61
66
|
|
|
62
67
|
#runnerStarted: PromiseWithResolvers<undefined> = Promise.withResolvers();
|
|
63
68
|
#runnerStopped: PromiseWithResolvers<undefined> = Promise.withResolvers();
|
|
@@ -74,17 +79,21 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
74
79
|
this.#managerDriver = managerDriver;
|
|
75
80
|
this.#inlineClient = inlineClient;
|
|
76
81
|
this.#config = config;
|
|
77
|
-
this.#actorRouter = createActorRouter(
|
|
82
|
+
this.#actorRouter = createActorRouter(
|
|
83
|
+
runConfig,
|
|
84
|
+
this,
|
|
85
|
+
registryConfig.test.enabled,
|
|
86
|
+
);
|
|
78
87
|
|
|
79
88
|
// Create runner configuration
|
|
80
89
|
let hasDisconnected = false;
|
|
81
90
|
const runnerConfig: RunnerConfig = {
|
|
82
91
|
version: this.#version,
|
|
83
92
|
endpoint: config.endpoint,
|
|
84
|
-
token: config.token,
|
|
93
|
+
token: runConfig.token ?? config.token,
|
|
85
94
|
pegboardEndpoint: config.pegboardEndpoint,
|
|
86
95
|
namespace: config.namespace,
|
|
87
|
-
totalSlots: config.totalSlots,
|
|
96
|
+
totalSlots: runConfig.totalSlots ?? config.totalSlots,
|
|
88
97
|
runnerName: config.runnerName,
|
|
89
98
|
runnerKey: config.runnerKey,
|
|
90
99
|
metadata: {
|
|
@@ -186,9 +195,29 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
186
195
|
}
|
|
187
196
|
|
|
188
197
|
async setAlarm(actor: AnyActorInstance, timestamp: number): Promise<void> {
|
|
189
|
-
//
|
|
190
|
-
|
|
191
|
-
|
|
198
|
+
// Clear prev timeout
|
|
199
|
+
if (this.#alarmTimeout) {
|
|
200
|
+
this.#alarmTimeout.abort();
|
|
201
|
+
this.#alarmTimeout = undefined;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Set alarm
|
|
205
|
+
const delay = Math.max(0, timestamp - Date.now());
|
|
206
|
+
this.#alarmTimeout = setLongTimeout(() => {
|
|
207
|
+
actor._onAlarm();
|
|
208
|
+
this.#alarmTimeout = undefined;
|
|
209
|
+
}, delay);
|
|
210
|
+
|
|
211
|
+
// TODO: This call may not be needed on ActorInstance.start, but it does help ensure that the local state is synced with the alarm state
|
|
212
|
+
// Set alarm on Rivet
|
|
213
|
+
//
|
|
214
|
+
// This does not call an "alarm" event like Durable Objects.
|
|
215
|
+
// Instead, it just wakes the actor on the alarm (if not
|
|
216
|
+
// already awake).
|
|
217
|
+
//
|
|
218
|
+
// _onAlarm is automatically called on `ActorInstance.start` when waking
|
|
219
|
+
// again.
|
|
220
|
+
this.#runner.setAlarm(actor.id, timestamp);
|
|
192
221
|
}
|
|
193
222
|
|
|
194
223
|
async getDatabase(_actorId: string): Promise<unknown | undefined> {
|
|
@@ -382,9 +411,9 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
382
411
|
|
|
383
412
|
return streamSSE(c, async (stream) => {
|
|
384
413
|
// Runner id should be set if the runner started
|
|
385
|
-
const
|
|
386
|
-
invariant(
|
|
387
|
-
stream.writeSSE({ data:
|
|
414
|
+
const payload = this.#runner.getServerlessInitPacket();
|
|
415
|
+
invariant(payload, "runnerId not set");
|
|
416
|
+
stream.writeSSE({ data: payload });
|
|
388
417
|
|
|
389
418
|
return this.#runnerStopped.promise;
|
|
390
419
|
});
|
|
@@ -123,7 +123,11 @@ export class FileSystemManagerDriver implements ManagerDriver {
|
|
|
123
123
|
this,
|
|
124
124
|
inlineClient,
|
|
125
125
|
);
|
|
126
|
-
this.#actorRouter = createActorRouter(
|
|
126
|
+
this.#actorRouter = createActorRouter(
|
|
127
|
+
this.#runConfig,
|
|
128
|
+
this.#actorDriver,
|
|
129
|
+
registryConfig.test.enabled,
|
|
130
|
+
);
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
async sendRequest(actorId: string, actorRequest: Request): Promise<Response> {
|
package/src/manager/driver.ts
CHANGED
package/src/manager/router.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
|
|
2
2
|
import * as cbor from "cbor-x";
|
|
3
3
|
import {
|
|
4
4
|
Hono,
|
|
5
|
-
Context as HonoContext,
|
|
5
|
+
type Context as HonoContext,
|
|
6
6
|
type MiddlewareHandler,
|
|
7
|
-
Next,
|
|
7
|
+
type Next,
|
|
8
8
|
} from "hono";
|
|
9
9
|
import { cors as corsMiddleware } from "hono/cors";
|
|
10
10
|
import { createMiddleware } from "hono/factory";
|
|
@@ -80,45 +80,53 @@ export function createManagerRouter(
|
|
|
80
80
|
runConfig: RunConfig,
|
|
81
81
|
managerDriver: ManagerDriver,
|
|
82
82
|
serverlessActorDriverBuilder: (() => ActorDriver) | undefined,
|
|
83
|
-
): { router: Hono; openapi: OpenAPIHono
|
|
83
|
+
): { router: Hono; openapi: OpenAPIHono } {
|
|
84
84
|
const router = new OpenAPIHono({ strict: false }).basePath(
|
|
85
85
|
runConfig.basePath,
|
|
86
86
|
);
|
|
87
87
|
|
|
88
88
|
router.use("*", loggerMiddleware(logger()));
|
|
89
89
|
|
|
90
|
-
const cors = runConfig.cors
|
|
91
|
-
? corsMiddleware(runConfig.cors)
|
|
92
|
-
: createMiddleware((_c, next) => next());
|
|
93
|
-
|
|
94
90
|
if (serverlessActorDriverBuilder) {
|
|
95
|
-
addServerlessRoutes(serverlessActorDriverBuilder, router
|
|
91
|
+
addServerlessRoutes(runConfig, serverlessActorDriverBuilder, router);
|
|
96
92
|
} else {
|
|
97
|
-
addManagerRoutes(registryConfig, runConfig, managerDriver, router
|
|
93
|
+
addManagerRoutes(registryConfig, runConfig, managerDriver, router);
|
|
98
94
|
}
|
|
99
95
|
|
|
100
96
|
// Error handling
|
|
101
97
|
router.notFound(handleRouteNotFound);
|
|
102
98
|
router.onError(handleRouteError);
|
|
103
99
|
|
|
104
|
-
return { router: router as Hono, openapi: router
|
|
100
|
+
return { router: router as Hono, openapi: router };
|
|
105
101
|
}
|
|
106
102
|
|
|
107
103
|
function addServerlessRoutes(
|
|
108
|
-
|
|
104
|
+
runConfig: RunConfig,
|
|
105
|
+
serverlessActorDriverBuilder: (
|
|
106
|
+
token: string | undefined,
|
|
107
|
+
totalSlots: number | undefined,
|
|
108
|
+
) => ActorDriver,
|
|
109
109
|
router: OpenAPIHono,
|
|
110
|
-
cors: MiddlewareHandler,
|
|
111
110
|
) {
|
|
111
|
+
// Apply CORS
|
|
112
|
+
if (runConfig.cors) router.use("*", corsMiddleware(runConfig.cors));
|
|
113
|
+
|
|
112
114
|
// GET /
|
|
113
|
-
router.get("/",
|
|
115
|
+
router.get("/", (c) => {
|
|
114
116
|
return c.text(
|
|
115
117
|
"This is a RivetKit server.\n\nLearn more at https://rivetkit.org",
|
|
116
118
|
);
|
|
117
119
|
});
|
|
118
120
|
|
|
119
121
|
// Serverless start endpoint
|
|
120
|
-
router.get("/start",
|
|
121
|
-
const
|
|
122
|
+
router.get("/start", async (c) => {
|
|
123
|
+
const token = c.req.header("x-rivet-token");
|
|
124
|
+
let totalSlots: number | undefined = parseInt(
|
|
125
|
+
c.req.header("x-rivetkit-total-slots") as any,
|
|
126
|
+
);
|
|
127
|
+
if (isNaN(totalSlots)) totalSlots = undefined;
|
|
128
|
+
|
|
129
|
+
const actorDriver = serverlessActorDriverBuilder(token, totalSlots);
|
|
122
130
|
invariant(
|
|
123
131
|
actorDriver.serverlessHandleStart,
|
|
124
132
|
"missing serverlessHandleStart on ActorDriver",
|
|
@@ -126,7 +134,7 @@ function addServerlessRoutes(
|
|
|
126
134
|
return await actorDriver.serverlessHandleStart(c);
|
|
127
135
|
});
|
|
128
136
|
|
|
129
|
-
router.get("/health",
|
|
137
|
+
router.get("/health", (c) => {
|
|
130
138
|
return c.text("ok");
|
|
131
139
|
});
|
|
132
140
|
}
|
|
@@ -136,13 +144,34 @@ function addManagerRoutes(
|
|
|
136
144
|
runConfig: RunConfig,
|
|
137
145
|
managerDriver: ManagerDriver,
|
|
138
146
|
router: OpenAPIHono,
|
|
139
|
-
cors: MiddlewareHandler,
|
|
140
147
|
) {
|
|
148
|
+
// Serve inspector BEFORE the rest of the routes, since this has a special
|
|
149
|
+
// CORS config that should take precedence for the `/inspector` path
|
|
150
|
+
if (isInspectorEnabled(runConfig, "manager")) {
|
|
151
|
+
if (!managerDriver.inspector) {
|
|
152
|
+
throw new Unsupported("inspector");
|
|
153
|
+
}
|
|
154
|
+
router.route(
|
|
155
|
+
"/inspect",
|
|
156
|
+
new Hono<{ Variables: { inspector: any } }>()
|
|
157
|
+
.use(corsMiddleware(runConfig.inspector.cors))
|
|
158
|
+
.use(secureInspector(runConfig))
|
|
159
|
+
.use((c, next) => {
|
|
160
|
+
c.set("inspector", managerDriver.inspector!);
|
|
161
|
+
return next();
|
|
162
|
+
})
|
|
163
|
+
.route("/", createManagerInspectorRouter()),
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Apply CORS
|
|
168
|
+
if (runConfig.cors) router.use("*", corsMiddleware(runConfig.cors));
|
|
169
|
+
|
|
141
170
|
// Actor gateway
|
|
142
|
-
router.use("*",
|
|
171
|
+
router.use("*", actorGateway.bind(undefined, runConfig, managerDriver));
|
|
143
172
|
|
|
144
173
|
// GET /
|
|
145
|
-
router.get("/",
|
|
174
|
+
router.get("/", (c) => {
|
|
146
175
|
return c.text(
|
|
147
176
|
"This is a RivetKit server.\n\nLearn more at https://rivetkit.org",
|
|
148
177
|
);
|
|
@@ -151,7 +180,6 @@ function addManagerRoutes(
|
|
|
151
180
|
// GET /actors
|
|
152
181
|
{
|
|
153
182
|
const route = createRoute({
|
|
154
|
-
middleware: [cors],
|
|
155
183
|
method: "get",
|
|
156
184
|
path: "/actors",
|
|
157
185
|
request: {
|
|
@@ -224,7 +252,6 @@ function addManagerRoutes(
|
|
|
224
252
|
// PUT /actors
|
|
225
253
|
{
|
|
226
254
|
const route = createRoute({
|
|
227
|
-
middleware: [cors],
|
|
228
255
|
method: "put",
|
|
229
256
|
path: "/actors",
|
|
230
257
|
request: {
|
|
@@ -277,7 +304,6 @@ function addManagerRoutes(
|
|
|
277
304
|
// POST /actors
|
|
278
305
|
{
|
|
279
306
|
const route = createRoute({
|
|
280
|
-
middleware: [cors],
|
|
281
307
|
method: "post",
|
|
282
308
|
path: "/actors",
|
|
283
309
|
request: {
|
|
@@ -317,7 +343,6 @@ function addManagerRoutes(
|
|
|
317
343
|
// // DELETE /actors/{actor_id}
|
|
318
344
|
// {
|
|
319
345
|
// const route = createRoute({
|
|
320
|
-
// middleware: [cors],
|
|
321
346
|
// method: "delete",
|
|
322
347
|
// path: "/actors/{actor_id}",
|
|
323
348
|
// request: {
|
|
@@ -538,7 +563,7 @@ function addManagerRoutes(
|
|
|
538
563
|
});
|
|
539
564
|
}
|
|
540
565
|
|
|
541
|
-
router.get("/health",
|
|
566
|
+
router.get("/health", (c) => {
|
|
542
567
|
return c.text("ok");
|
|
543
568
|
});
|
|
544
569
|
|
|
@@ -546,23 +571,6 @@ function addManagerRoutes(
|
|
|
546
571
|
registryConfig,
|
|
547
572
|
router as unknown as Hono,
|
|
548
573
|
);
|
|
549
|
-
|
|
550
|
-
if (isInspectorEnabled(runConfig, "manager")) {
|
|
551
|
-
if (!managerDriver.inspector) {
|
|
552
|
-
throw new Unsupported("inspector");
|
|
553
|
-
}
|
|
554
|
-
router.route(
|
|
555
|
-
"/inspect",
|
|
556
|
-
new Hono<{ Variables: { inspector: any } }>()
|
|
557
|
-
.use(corsMiddleware(runConfig.inspector.cors))
|
|
558
|
-
.use(secureInspector(runConfig))
|
|
559
|
-
.use((c, next) => {
|
|
560
|
-
c.set("inspector", managerDriver.inspector!);
|
|
561
|
-
return next();
|
|
562
|
-
})
|
|
563
|
-
.route("/", createManagerInspectorRouter()),
|
|
564
|
-
);
|
|
565
|
-
}
|
|
566
574
|
}
|
|
567
575
|
|
|
568
576
|
function createApiActor(actor: ActorOutput): ApiActor {
|
package/src/registry/mod.ts
CHANGED
|
@@ -108,7 +108,7 @@ export class Registry<A extends RegistryActors> {
|
|
|
108
108
|
console.log(` - ${k}:${padding}${v}`);
|
|
109
109
|
}
|
|
110
110
|
if (isInspectorEnabled(config, "manager") && managerDriver.inspector) {
|
|
111
|
-
console.log(` - Inspector:
|
|
111
|
+
console.log(` - Inspector: ${getInspectorUrl(config)}`);
|
|
112
112
|
}
|
|
113
113
|
console.log();
|
|
114
114
|
}
|
|
@@ -215,7 +215,16 @@ export class Registry<A extends RegistryActors> {
|
|
|
215
215
|
console.log();
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
let serverlessActorDriverBuilder:
|
|
218
|
+
let serverlessActorDriverBuilder:
|
|
219
|
+
| ((token?: string, totalSlots?: number) => ActorDriver)
|
|
220
|
+
| undefined = (
|
|
221
|
+
token: string | undefined,
|
|
222
|
+
totalSlots: number | undefined,
|
|
223
|
+
) => {
|
|
224
|
+
// Override config
|
|
225
|
+
if (token) config.token = token;
|
|
226
|
+
if (totalSlots) config.totalSlots = totalSlots;
|
|
227
|
+
|
|
219
228
|
return driver.actor(this.#config, config, managerDriver, client);
|
|
220
229
|
};
|
|
221
230
|
|
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
ManagerDriver,
|
|
16
16
|
} from "@/driver-helpers/mod";
|
|
17
17
|
import type { Encoding, UniversalWebSocket } from "@/mod";
|
|
18
|
+
import { uint8ArrayToBase64 } from "@/serde";
|
|
18
19
|
import { combineUrlPath } from "@/utils";
|
|
19
20
|
import { sendHttpRequestToActor } from "./actor-http-client";
|
|
20
21
|
import {
|
|
@@ -140,7 +141,7 @@ export class RemoteManagerDriver implements ManagerDriver {
|
|
|
140
141
|
key: serializeActorKey(key),
|
|
141
142
|
runner_name_selector: this.#config.runnerName,
|
|
142
143
|
input: actorInput
|
|
143
|
-
? cbor.encode(actorInput)
|
|
144
|
+
? uint8ArrayToBase64(cbor.encode(actorInput))
|
|
144
145
|
: undefined,
|
|
145
146
|
crash_policy: "sleep",
|
|
146
147
|
});
|
|
@@ -175,7 +176,7 @@ export class RemoteManagerDriver implements ManagerDriver {
|
|
|
175
176
|
name,
|
|
176
177
|
runner_name_selector: this.#config.runnerName,
|
|
177
178
|
key: serializeActorKey(key),
|
|
178
|
-
input: input ? cbor.encode(input)
|
|
179
|
+
input: input ? uint8ArrayToBase64(cbor.encode(input)) : undefined,
|
|
179
180
|
crash_policy: "sleep",
|
|
180
181
|
});
|
|
181
182
|
const actorId = result.actor.actor_id;
|
package/src/serde.ts
CHANGED
|
@@ -5,6 +5,21 @@ import type { VersionedDataHandler } from "@/common/versioned-data";
|
|
|
5
5
|
import type { Encoding } from "@/mod";
|
|
6
6
|
import { jsonStringifyCompat } from "./actor/protocol/serde";
|
|
7
7
|
|
|
8
|
+
export function uint8ArrayToBase64(uint8Array: Uint8Array): string {
|
|
9
|
+
// Check if Buffer is available (Node.js)
|
|
10
|
+
if (typeof Buffer !== "undefined") {
|
|
11
|
+
return Buffer.from(uint8Array).toString("base64");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Browser environment - use btoa
|
|
15
|
+
let binary = "";
|
|
16
|
+
const len = uint8Array.byteLength;
|
|
17
|
+
for (let i = 0; i < len; i++) {
|
|
18
|
+
binary += String.fromCharCode(uint8Array[i]);
|
|
19
|
+
}
|
|
20
|
+
return btoa(binary);
|
|
21
|
+
}
|
|
22
|
+
|
|
8
23
|
export function encodingIsBinary(encoding: Encoding): boolean {
|
|
9
24
|
if (encoding === "json") {
|
|
10
25
|
return false;
|