@rivetkit/cloudflare-workers 2.1.6 → 2.1.7
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/mod.cjs +73 -25
- package/dist/mod.cjs.map +1 -1
- package/dist/mod.d.cts +1 -1
- package/dist/mod.d.ts +1 -1
- package/dist/mod.js +73 -25
- package/dist/mod.js.map +1 -1
- package/package.json +2 -2
- package/src/actor-driver.ts +46 -8
- package/src/actor-handler-do.ts +4 -1
- package/src/actor-kv.ts +67 -18
- package/src/config.ts +2 -4
- package/src/handler.ts +12 -7
package/src/actor-driver.ts
CHANGED
|
@@ -6,7 +6,6 @@ import type {
|
|
|
6
6
|
RegistryConfig,
|
|
7
7
|
} from "rivetkit";
|
|
8
8
|
import { lookupInRegistry } from "rivetkit";
|
|
9
|
-
import type { Client } from "rivetkit/client";
|
|
10
9
|
import type {
|
|
11
10
|
ActorDriver,
|
|
12
11
|
AnyActorInstance,
|
|
@@ -14,7 +13,14 @@ import type {
|
|
|
14
13
|
} from "rivetkit/driver-helpers";
|
|
15
14
|
import { promiseWithResolvers } from "rivetkit/utils";
|
|
16
15
|
import { logger } from "./log";
|
|
17
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
kvDelete,
|
|
18
|
+
kvDeleteRange,
|
|
19
|
+
kvGet,
|
|
20
|
+
kvListPrefix,
|
|
21
|
+
kvListRange,
|
|
22
|
+
kvPut,
|
|
23
|
+
} from "./actor-kv";
|
|
18
24
|
import { GLOBAL_KV_KEYS } from "./global-kv";
|
|
19
25
|
import { getCloudflareAmbientEnv } from "./handler";
|
|
20
26
|
import { parseActorId } from "./actor-id";
|
|
@@ -105,13 +111,13 @@ export class ActorGlobalState {
|
|
|
105
111
|
export class CloudflareActorsActorDriver implements ActorDriver {
|
|
106
112
|
#registryConfig: RegistryConfig;
|
|
107
113
|
#managerDriver: ManagerDriver;
|
|
108
|
-
#inlineClient:
|
|
114
|
+
#inlineClient: any;
|
|
109
115
|
#globalState: CloudflareDurableObjectGlobalState;
|
|
110
116
|
|
|
111
117
|
constructor(
|
|
112
118
|
registryConfig: RegistryConfig,
|
|
113
119
|
managerDriver: ManagerDriver,
|
|
114
|
-
inlineClient:
|
|
120
|
+
inlineClient: any,
|
|
115
121
|
globalState: CloudflareDurableObjectGlobalState,
|
|
116
122
|
) {
|
|
117
123
|
this.#registryConfig = registryConfig;
|
|
@@ -143,7 +149,12 @@ export class CloudflareActorsActorDriver implements ActorDriver {
|
|
|
143
149
|
// Create new actor state if it doesn't exist
|
|
144
150
|
if (!actorState) {
|
|
145
151
|
actorState = new ActorGlobalState();
|
|
146
|
-
actorState.actorPromise = promiseWithResolvers((reason) =>
|
|
152
|
+
actorState.actorPromise = promiseWithResolvers((reason) =>
|
|
153
|
+
logger().warn({
|
|
154
|
+
msg: "unhandled actor promise rejection",
|
|
155
|
+
reason,
|
|
156
|
+
}),
|
|
157
|
+
);
|
|
147
158
|
this.#globalState.setActorState(doState.ctx, actorState);
|
|
148
159
|
} else if (actorState.actorPromise) {
|
|
149
160
|
// Another request is already loading this actor, wait for it
|
|
@@ -191,7 +202,8 @@ export class CloudflareActorsActorDriver implements ActorDriver {
|
|
|
191
202
|
actorState.actorInstance = definition.instantiate();
|
|
192
203
|
|
|
193
204
|
// Start actor
|
|
194
|
-
|
|
205
|
+
const actorInstance = actorState.actorInstance as any;
|
|
206
|
+
await actorInstance.start(
|
|
195
207
|
this,
|
|
196
208
|
this.#inlineClient,
|
|
197
209
|
actorId,
|
|
@@ -256,13 +268,39 @@ export class CloudflareActorsActorDriver implements ActorDriver {
|
|
|
256
268
|
}
|
|
257
269
|
}
|
|
258
270
|
|
|
271
|
+
async kvDeleteRange(
|
|
272
|
+
actorId: string,
|
|
273
|
+
start: Uint8Array,
|
|
274
|
+
end: Uint8Array,
|
|
275
|
+
): Promise<void> {
|
|
276
|
+
const sql = this.#getDOCtx(actorId).storage.sql;
|
|
277
|
+
kvDeleteRange(sql, start, end);
|
|
278
|
+
}
|
|
279
|
+
|
|
259
280
|
async kvListPrefix(
|
|
260
281
|
actorId: string,
|
|
261
282
|
prefix: Uint8Array,
|
|
283
|
+
options?: {
|
|
284
|
+
reverse?: boolean;
|
|
285
|
+
limit?: number;
|
|
286
|
+
},
|
|
262
287
|
): Promise<[Uint8Array, Uint8Array][]> {
|
|
263
288
|
const sql = this.#getDOCtx(actorId).storage.sql;
|
|
264
289
|
|
|
265
|
-
return kvListPrefix(sql, prefix);
|
|
290
|
+
return kvListPrefix(sql, prefix, options);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
async kvListRange(
|
|
294
|
+
actorId: string,
|
|
295
|
+
start: Uint8Array,
|
|
296
|
+
end: Uint8Array,
|
|
297
|
+
options?: {
|
|
298
|
+
reverse?: boolean;
|
|
299
|
+
limit?: number;
|
|
300
|
+
},
|
|
301
|
+
): Promise<[Uint8Array, Uint8Array][]> {
|
|
302
|
+
const sql = this.#getDOCtx(actorId).storage.sql;
|
|
303
|
+
return kvListRange(sql, start, end, options);
|
|
266
304
|
}
|
|
267
305
|
|
|
268
306
|
startDestroy(actorId: string): void {
|
|
@@ -323,7 +361,7 @@ export function createCloudflareActorsActorDriverBuilder(
|
|
|
323
361
|
return (
|
|
324
362
|
config: RegistryConfig,
|
|
325
363
|
managerDriver: ManagerDriver,
|
|
326
|
-
inlineClient:
|
|
364
|
+
inlineClient: any,
|
|
327
365
|
) => {
|
|
328
366
|
return new CloudflareActorsActorDriver(
|
|
329
367
|
config,
|
package/src/actor-handler-do.ts
CHANGED
|
@@ -175,7 +175,10 @@ export function createActorDurableObject(
|
|
|
175
175
|
const managerDriver = new CloudflareActorsManagerDriver();
|
|
176
176
|
|
|
177
177
|
// Create inline client
|
|
178
|
-
|
|
178
|
+
// Avoid expensive type expansion in downstream DTS generation.
|
|
179
|
+
const inlineClient: any = (createClientWithDriver as any)(
|
|
180
|
+
managerDriver,
|
|
181
|
+
);
|
|
179
182
|
|
|
180
183
|
// Create actor driver builder
|
|
181
184
|
const actorDriverBuilder =
|
package/src/actor-kv.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const DEFAULT_LIST_LIMIT = 16_384;
|
|
2
|
+
|
|
1
3
|
export function kvGet(sql: SqlStorage, key: Uint8Array): Uint8Array | null {
|
|
2
4
|
const cursor = sql.exec(
|
|
3
5
|
"SELECT value FROM _rivetkit_kv_storage WHERE key = ?",
|
|
@@ -27,27 +29,61 @@ export function kvDelete(sql: SqlStorage, key: Uint8Array): void {
|
|
|
27
29
|
sql.exec("DELETE FROM _rivetkit_kv_storage WHERE key = ?", key);
|
|
28
30
|
}
|
|
29
31
|
|
|
32
|
+
export function kvDeleteRange(
|
|
33
|
+
sql: SqlStorage,
|
|
34
|
+
start: Uint8Array,
|
|
35
|
+
end: Uint8Array,
|
|
36
|
+
): void {
|
|
37
|
+
sql.exec(
|
|
38
|
+
"DELETE FROM _rivetkit_kv_storage WHERE key >= ? AND key < ?",
|
|
39
|
+
start,
|
|
40
|
+
end,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
30
44
|
export function kvListPrefix(
|
|
31
45
|
sql: SqlStorage,
|
|
32
46
|
prefix: Uint8Array,
|
|
47
|
+
options?: {
|
|
48
|
+
reverse?: boolean;
|
|
49
|
+
limit?: number;
|
|
50
|
+
},
|
|
33
51
|
): [Uint8Array, Uint8Array][] {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
for (const row of cursor.raw()) {
|
|
38
|
-
const key = toUint8Array(row[0]);
|
|
39
|
-
const value = toUint8Array(row[1]);
|
|
40
|
-
|
|
41
|
-
// Check if key starts with prefix
|
|
42
|
-
if (hasPrefix(key, prefix)) {
|
|
43
|
-
entries.push([key, value]);
|
|
44
|
-
}
|
|
52
|
+
const upperBound = computePrefixUpperBound(prefix);
|
|
53
|
+
if (upperBound) {
|
|
54
|
+
return kvListRange(sql, prefix, upperBound, options);
|
|
45
55
|
}
|
|
46
56
|
|
|
47
|
-
|
|
57
|
+
const direction = options?.reverse ? "DESC" : "ASC";
|
|
58
|
+
const limit = options?.limit ?? DEFAULT_LIST_LIMIT;
|
|
59
|
+
const cursor = sql.exec(
|
|
60
|
+
`SELECT key, value FROM _rivetkit_kv_storage WHERE key >= ? ORDER BY key ${direction} LIMIT ?`,
|
|
61
|
+
prefix,
|
|
62
|
+
limit,
|
|
63
|
+
);
|
|
64
|
+
return readEntries(cursor);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function kvListRange(
|
|
68
|
+
sql: SqlStorage,
|
|
69
|
+
start: Uint8Array,
|
|
70
|
+
end: Uint8Array,
|
|
71
|
+
options?: {
|
|
72
|
+
reverse?: boolean;
|
|
73
|
+
limit?: number;
|
|
74
|
+
},
|
|
75
|
+
): [Uint8Array, Uint8Array][] {
|
|
76
|
+
const direction = options?.reverse ? "DESC" : "ASC";
|
|
77
|
+
const limit = options?.limit ?? DEFAULT_LIST_LIMIT;
|
|
78
|
+
const cursor = sql.exec(
|
|
79
|
+
`SELECT key, value FROM _rivetkit_kv_storage WHERE key >= ? AND key < ? ORDER BY key ${direction} LIMIT ?`,
|
|
80
|
+
start,
|
|
81
|
+
end,
|
|
82
|
+
limit,
|
|
83
|
+
);
|
|
84
|
+
return readEntries(cursor);
|
|
48
85
|
}
|
|
49
86
|
|
|
50
|
-
// Helper function to convert SqlStorageValue to Uint8Array
|
|
51
87
|
function toUint8Array(
|
|
52
88
|
value: string | number | ArrayBuffer | Uint8Array | null,
|
|
53
89
|
): Uint8Array {
|
|
@@ -62,10 +98,23 @@ function toUint8Array(
|
|
|
62
98
|
);
|
|
63
99
|
}
|
|
64
100
|
|
|
65
|
-
function
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
101
|
+
function readEntries(
|
|
102
|
+
cursor: ReturnType<SqlStorage["exec"]>,
|
|
103
|
+
): [Uint8Array, Uint8Array][] {
|
|
104
|
+
const entries: [Uint8Array, Uint8Array][] = [];
|
|
105
|
+
for (const row of cursor.raw()) {
|
|
106
|
+
entries.push([toUint8Array(row[0]), toUint8Array(row[1])]);
|
|
69
107
|
}
|
|
70
|
-
return
|
|
108
|
+
return entries;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function computePrefixUpperBound(prefix: Uint8Array): Uint8Array | null {
|
|
112
|
+
const upperBound = prefix.slice();
|
|
113
|
+
for (let i = upperBound.length - 1; i >= 0; i--) {
|
|
114
|
+
if (upperBound[i] !== 0xff) {
|
|
115
|
+
upperBound[i]++;
|
|
116
|
+
return upperBound.slice(0, i + 1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
71
120
|
}
|
package/src/config.ts
CHANGED
|
@@ -5,16 +5,14 @@ const ConfigSchemaBase = z.object({
|
|
|
5
5
|
/** Path that the Rivet manager API will be mounted. */
|
|
6
6
|
managerPath: z.string().optional().default("/api/rivet"),
|
|
7
7
|
|
|
8
|
-
/** Runner key for authentication. */
|
|
8
|
+
/** Deprecated. Runner key for authentication. */
|
|
9
9
|
runnerKey: z.string().optional(),
|
|
10
10
|
|
|
11
11
|
/** Disable the welcome message. */
|
|
12
12
|
noWelcome: z.boolean().optional().default(false),
|
|
13
13
|
|
|
14
14
|
fetch: z
|
|
15
|
-
.custom<
|
|
16
|
-
ExportedHandlerFetchHandler<{ RIVET: Client<any> }, unknown>
|
|
17
|
-
>()
|
|
15
|
+
.custom<ExportedHandlerFetchHandler<{ RIVET: Client<any> }, unknown>>()
|
|
18
16
|
.optional(),
|
|
19
17
|
});
|
|
20
18
|
export const ConfigSchema = ConfigSchemaBase.default(() =>
|
package/src/handler.ts
CHANGED
|
@@ -91,7 +91,8 @@ export function createInlineClient<R extends Registry<any>>(
|
|
|
91
91
|
);
|
|
92
92
|
|
|
93
93
|
// Create client using the manager driver
|
|
94
|
-
|
|
94
|
+
// Avoid excessive generic expansion in DTS generation.
|
|
95
|
+
const client = (createClientWithDriver as any)(managerDriver) as Client<R>;
|
|
95
96
|
|
|
96
97
|
return { client, fetch: router.fetch.bind(router), config, ActorHandler };
|
|
97
98
|
}
|
|
@@ -103,14 +104,18 @@ export function createInlineClient<R extends Registry<any>>(
|
|
|
103
104
|
*
|
|
104
105
|
* This includes a `fetch` handler and `ActorHandler` Durable Object.
|
|
105
106
|
*/
|
|
106
|
-
export function createHandler
|
|
107
|
-
registry:
|
|
107
|
+
export function createHandler(
|
|
108
|
+
registry: Registry<any>,
|
|
108
109
|
inputConfig?: InputConfig,
|
|
109
110
|
): HandlerOutput {
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
const inline = (createInlineClient as any)(registry, inputConfig);
|
|
112
|
+
const client = inline.client as any;
|
|
113
|
+
const fetch = inline.fetch as (
|
|
114
|
+
request: Request,
|
|
115
|
+
...args: any
|
|
116
|
+
) => Response | Promise<Response>;
|
|
117
|
+
const config = inline.config as Config;
|
|
118
|
+
const ActorHandler = inline.ActorHandler as DurableObjectConstructor;
|
|
114
119
|
|
|
115
120
|
// Create Cloudflare handler
|
|
116
121
|
const handler = {
|