Skip to content

Commit 0a46ce9

Browse files
NathanFlurryjog1t
authored andcommitted
chore(rivetkit): add listing actors by only name to manager api
1 parent 94422d8 commit 0a46ce9

File tree

9 files changed

+105
-16
lines changed

9 files changed

+105
-16
lines changed

rivetkit-typescript/packages/cloudflare-workers/src/manager-driver.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
type GetOrCreateWithKeyInput,
88
type GetWithKeyInput,
99
generateRandomString,
10+
type ListActorsInput,
1011
type ManagerDisplayInformation,
1112
type ManagerDriver,
1213
WS_PROTOCOL_ACTOR,
@@ -348,6 +349,14 @@ export class CloudflareActorsManagerDriver implements ManagerDriver {
348349
};
349350
}
350351

352+
async listActors({ c, name }: ListActorsInput): Promise<ActorOutput[]> {
353+
logger().warn({
354+
msg: "listActors not fully implemented for Cloudflare Workers",
355+
name,
356+
});
357+
return [];
358+
}
359+
351360
// Helper method to build actor output from an ID
352361
async #buildActorOutput(
353362
c: any,

rivetkit-typescript/packages/rivetkit/scripts/dump-openapi.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ function main() {
3232
getWithKey: unimplemented,
3333
getOrCreateWithKey: unimplemented,
3434
createActor: unimplemented,
35+
listActors: unimplemented,
3536
sendRequest: unimplemented,
3637
openWebSocket: unimplemented,
3738
proxyRequest: unimplemented,

rivetkit-typescript/packages/rivetkit/src/driver-helpers/mod.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export type {
2424
GetForIdInput,
2525
GetOrCreateWithKeyInput,
2626
GetWithKeyInput,
27+
ListActorsInput,
2728
ManagerDisplayInformation,
2829
ManagerDriver,
2930
} from "@/manager/driver";

rivetkit-typescript/packages/rivetkit/src/driver-test-suite/test-inline-client-driver.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
type GetOrCreateWithKeyInput,
2626
type GetWithKeyInput,
2727
HEADER_ACTOR_ID,
28+
type ListActorsInput,
2829
type ManagerDisplayInformation,
2930
type ManagerDriver,
3031
} from "@/driver-helpers/mod";
@@ -73,6 +74,9 @@ export function createTestInlineClientDriver(
7374
input,
7475
]);
7576
},
77+
listActors(input: ListActorsInput): Promise<ActorOutput[]> {
78+
return makeInlineRequest(endpoint, encoding, "listActors", [input]);
79+
},
7680
async sendRequest(
7781
actorId: string,
7882
actorRequest: Request,

rivetkit-typescript/packages/rivetkit/src/drivers/file-system/manager.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type {
1717
GetForIdInput,
1818
GetOrCreateWithKeyInput,
1919
GetWithKeyInput,
20+
ListActorsInput,
2021
ManagerDriver,
2122
} from "@/driver-helpers/mod";
2223
import { ManagerInspector } from "@/inspector/manager";
@@ -333,6 +334,31 @@ export class FileSystemManagerDriver implements ManagerDriver {
333334
};
334335
}
335336

337+
async listActors({ name }: ListActorsInput): Promise<ActorOutput[]> {
338+
const actors: ActorOutput[] = [];
339+
const itr = this.#state.getActorsIterator({});
340+
341+
for await (const actor of itr) {
342+
if (actor.name === name) {
343+
actors.push({
344+
actorId: actor.actorId,
345+
name: actor.name,
346+
key: actor.key as string[],
347+
createTs: Number(actor.createdAt),
348+
});
349+
}
350+
}
351+
352+
// Sort by create ts desc (most recent first)
353+
actors.sort((a, b) => {
354+
const aTs = a.createTs ?? 0;
355+
const bTs = b.createTs ?? 0;
356+
return bTs - aTs;
357+
});
358+
359+
return actors;
360+
}
361+
336362
displayInformation(): ManagerDisplayInformation {
337363
return {
338364
name: this.#state.persist ? "File System" : "Memory",

rivetkit-typescript/packages/rivetkit/src/manager/driver.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface ManagerDriver {
1414
getWithKey(input: GetWithKeyInput): Promise<ActorOutput | undefined>;
1515
getOrCreateWithKey(input: GetOrCreateWithKeyInput): Promise<ActorOutput>;
1616
createActor(input: CreateInput): Promise<ActorOutput>;
17+
listActors(input: ListActorsInput): Promise<ActorOutput[]>;
1718

1819
sendRequest(actorId: string, actorRequest: Request): Promise<Response>;
1920
openWebSocket(
@@ -92,8 +93,16 @@ export interface CreateInput<E extends Env = any> {
9293
region?: string;
9394
}
9495

96+
export interface ListActorsInput<E extends Env = any> {
97+
c?: HonoContext | undefined;
98+
name: string;
99+
key?: string;
100+
includeDestroyed?: boolean;
101+
}
102+
95103
export interface ActorOutput {
96104
actorId: string;
97105
name: string;
98106
key: ActorKey;
107+
createTs?: number;
99108
}

rivetkit-typescript/packages/rivetkit/src/manager/router.ts

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -289,17 +289,7 @@ function addManagerRoutes(
289289
if (key && !name) {
290290
return c.json(
291291
{
292-
error: "When providing 'key', 'name' must also be provided.",
293-
},
294-
400,
295-
);
296-
}
297-
298-
// Validate: must provide either actor_ids or (name + key)
299-
if (!actorIdsParsed && !key) {
300-
return c.json(
301-
{
302-
error: "Must provide either 'actor_ids' or both 'name' and 'key'.",
292+
error: "Name is required when key is provided.",
303293
},
304294
400,
305295
);
@@ -351,16 +341,33 @@ function addManagerRoutes(
351341
}
352342
}
353343
}
354-
} else if (key) {
355-
// At this point, name is guaranteed to be defined due to validation above
344+
} else if (key && name) {
356345
const actorOutput = await managerDriver.getWithKey({
357346
c,
358-
name: name!,
347+
name,
359348
key: [key], // Convert string to ActorKey array
360349
});
361350
if (actorOutput) {
362351
actors.push(actorOutput);
363352
}
353+
} else {
354+
if (!name) {
355+
return c.json(
356+
{
357+
error: "Name is required when not using actor_ids.",
358+
},
359+
400,
360+
);
361+
}
362+
363+
// List all actors with the given name
364+
const actorOutputs = await managerDriver.listActors({
365+
c,
366+
name,
367+
key,
368+
includeDestroyed: false,
369+
});
370+
actors.push(...actorOutputs);
364371
}
365372

366373
return c.json<ActorsListResponse>({
@@ -722,7 +729,7 @@ function createApiActor(
722729
key: serializeActorKey(actor.key),
723730
namespace_id: "default", // Assert default namespace
724731
runner_name_selector: runnerName,
725-
create_ts: Date.now(),
732+
create_ts: actor.createTs ?? Date.now(),
726733
connectable_ts: null,
727734
destroy_ts: null,
728735
sleep_ts: null,

rivetkit-typescript/packages/rivetkit/src/remote-manager-driver/api-endpoints.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export async function getActor(
2525
);
2626
}
2727

28-
// MARK: Get actor by id
28+
// MARK: Get actor by key
2929
export async function getActorByKey(
3030
config: ClientConfig,
3131
name: string,
@@ -39,6 +39,18 @@ export async function getActorByKey(
3939
);
4040
}
4141

42+
// MARK: List actors by name
43+
export async function listActorsByName(
44+
config: ClientConfig,
45+
name: string,
46+
): Promise<ActorsListResponse> {
47+
return apiCall<never, ActorsListResponse>(
48+
config,
49+
"GET",
50+
`/actors?name=${encodeURIComponent(name)}`,
51+
);
52+
}
53+
4254
// MARK: Get or create actor by id
4355
export async function getOrCreateActor(
4456
config: ClientConfig,

rivetkit-typescript/packages/rivetkit/src/remote-manager-driver/mod.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
GetForIdInput,
1313
GetOrCreateWithKeyInput,
1414
GetWithKeyInput,
15+
ListActorsInput,
1516
ManagerDisplayInformation,
1617
ManagerDriver,
1718
} from "@/driver-helpers/mod";
@@ -30,6 +31,7 @@ import {
3031
getActorByKey,
3132
getMetadata,
3233
getOrCreateActor,
34+
listActorsByName,
3335
} from "./api-endpoints";
3436
import { EngineApiError, getEndpoint } from "./api-utils";
3537
import { logger } from "./log";
@@ -255,6 +257,24 @@ export class RemoteManagerDriver implements ManagerDriver {
255257
};
256258
}
257259

260+
async listActors({ c, name }: ListActorsInput): Promise<ActorOutput[]> {
261+
// Wait for metadata check to complete if in progress
262+
if (this.#metadataPromise) {
263+
await this.#metadataPromise;
264+
}
265+
266+
logger().debug({ msg: "listing actors via engine api", name });
267+
268+
const response = await listActorsByName(this.#config, name);
269+
270+
return response.actors.map((actor) => ({
271+
actorId: actor.actor_id,
272+
name: actor.name,
273+
key: deserializeActorKey(actor.key),
274+
createTs: actor.create_ts,
275+
}));
276+
}
277+
258278
async destroyActor(actorId: string): Promise<void> {
259279
// Wait for metadata check to complete if in progress
260280
if (this.#metadataPromise) {

0 commit comments

Comments
 (0)