diff --git a/README.md b/README.md index 2f386cc..3f87a65 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ class Counter { } // Invoking the counter actor -const counter = actors.stub(Counter).id("counter-id"); +const counter = actors.proxy(Counter).id("counter-id"); // Increment counter await counter.increment(); // Get current count diff --git a/deno.json b/deno.json index 6b7f4a6..b8e51dc 100644 --- a/deno.json +++ b/deno.json @@ -3,8 +3,7 @@ "exports": { ".": "./src/actors/mod.ts", "./hono": "./src/actors/hono/middleware.ts", - "./proxy": "./src/actors/stub.ts", - "./stub": "./src/actors/stub.ts", + "./proxy": "./src/actors/proxy.ts", "./watch": "./src/actors/util/watch.ts", "./server-run": "./src/actors/server/run.ts", "./server-gen": "./src/actors/server/gen.ts", diff --git a/src/actors/mod.ts b/src/actors/mod.ts index b65b787..c337852 100644 --- a/src/actors/mod.ts +++ b/src/actors/mod.ts @@ -2,9 +2,9 @@ export interface Actor { } +export type { ActorProxy } from "./proxyutil.ts"; export { ActorRuntime } from "./runtime.ts"; export type { ActorConstructor } from "./runtime.ts"; export { ActorState } from "./state.ts"; export { type ActorStorage } from "./storage.ts"; -export type { ActorProxy, ActorProxy as ActorStub } from "./stubutil.ts"; export { actorId } from "./util/id.ts"; diff --git a/src/actors/stub.ts b/src/actors/proxy.ts similarity index 53% rename from src/actors/stub.ts rename to src/actors/proxy.ts index d925313..0cd48fe 100644 --- a/src/actors/stub.ts +++ b/src/actors/proxy.ts @@ -1,12 +1,12 @@ // deno-lint-ignore-file no-explicit-any -import type { Actor, ActorConstructor } from "./runtime.ts"; import { type ActorProxy, create, createHttpInvoker, - type StubFactory, -} from "./stubutil.ts"; -export type { ActorProxy, ActorProxy as ActorStub }; + type ProxyFactory, +} from "./proxyutil.ts"; +import type { Actor, ActorConstructor } from "./runtime.ts"; +export type { ActorProxy }; export interface ActorsServer { url: string; credentials?: RequestCredentials; @@ -18,19 +18,16 @@ export interface ActorsOptions { actorIdHeaderName?: string; errorHandling?: Record Error>; } -const stub = ( - actor: ActorConstructor | string, - options?: ActorsOptions | undefined, -): { id: StubFactory } => { - const factory = (id: string, discriminator?: string) => - createHttpInvoker(id, discriminator, options); - return create(actor, factory); -}; - /** * utilities to create and manage actors. */ export const actors = { - proxy: stub, - stub, + proxy: ( + actor: ActorConstructor | string, + options?: ActorsOptions | undefined, + ): { id: ProxyFactory } => { + const factory = (id: string, discriminator?: string) => + createHttpInvoker(id, discriminator, options); + return create(actor, factory); + }, }; diff --git a/src/actors/stubutil.ts b/src/actors/proxyutil.ts similarity index 98% rename from src/actors/stubutil.ts rename to src/actors/proxyutil.ts index 19783d6..6bed01f 100644 --- a/src/actors/stubutil.ts +++ b/src/actors/proxyutil.ts @@ -1,9 +1,9 @@ // deno-lint-ignore-file no-explicit-any import process from "node:process"; +import type { ActorsOptions, ActorsServer } from "./proxy.ts"; import type { InvokeRequest, InvokeResponse } from "./rpc.ts"; import type { Actor, ActorConstructor } from "./runtime.ts"; import { EVENT_STREAM_RESPONSE_HEADER, readFromStream } from "./stream.ts"; -import type { ActorsOptions, ActorsServer, ActorStub } from "./stub.ts"; import { type Channel, type ChannelUpgrader, @@ -20,10 +20,10 @@ export const ACTOR_CONSTRUCTOR_NAME_HEADER = "x-error-constructor-name"; export const ACTOR_DISCRIMINATOR_HEADER_NAME = "x-actor-discriminator"; export const ACTOR_DISCRIMINATOR_QS_NAME = "actor_discriminator"; -export type StubFactory = ( +export type ProxyFactory = ( id: string, discriminator?: string, -) => ActorStub; +) => ActorProxy; /** * Promise.prototype.then onfufilled callback type. */ @@ -200,8 +200,6 @@ export interface ProxyOptions { server: string; } -export type StubOptions = ProxyOptions; - export type PromisifyKey = Actor[key] extends (...args: infer Args) => Awaited ? Return extends ChannelUpgrader @@ -372,11 +370,9 @@ export const createRPCInvoker = < const resolver: RequestResolver = { response }; pendingRequests.set(id, resolver); const cleanup = () => { - if (!pendingRequests.has(id)) { - return; - } const channelClosed = new Error("Channel closed"); response.reject(channelClosed); + resolver.throw?.(channelClosed); resolver.stream?.close(); resolver.ch?.close(); }; @@ -514,7 +510,7 @@ export const create = ( invokerFactory: (id: string, discriminator?: string) => ActorInvoker, metadata?: unknown, disposer?: () => void, -): { id: StubFactory } => { +): { id: ProxyFactory } => { const name = typeof actor === "string" ? actor : actor.name; return { id: (id: string, discriminator?: string): ActorProxy => { diff --git a/src/actors/rpc.ts b/src/actors/rpc.ts index a4036f0..ed7a41e 100644 --- a/src/actors/rpc.ts +++ b/src/actors/rpc.ts @@ -1,6 +1,6 @@ // deno-lint-ignore-file no-explicit-any +import type { ActorInvoker } from "./proxyutil.ts"; import { isEventStreamResponse } from "./stream.ts"; -import type { ActorInvoker } from "./stubutil.ts"; import { type ChannelUpgrader, type DuplexChannel, diff --git a/src/actors/runtime.test.ts b/src/actors/runtime.test.ts index e0c608c..b539224 100644 --- a/src/actors/runtime.test.ts +++ b/src/actors/runtime.test.ts @@ -1,7 +1,7 @@ import { assertEquals, assertFalse } from "jsr:@std/assert@^1.0.5"; +import { actors } from "./proxy.ts"; import { ActorRuntime } from "./runtime.ts"; import type { ActorState } from "./state.ts"; -import { actors } from "./stub.ts"; import type { ChannelUpgrader } from "./util/channels/channel.ts"; import { WatchTarget } from "./util/watch.ts"; @@ -32,7 +32,7 @@ class Counter { } callSayHello(): Promise { - const hello = this.state.stub(Hello).id(this.state.id); + const hello = this.state.proxy(Hello).id(this.state.id); return hello.sayHello(); } @@ -59,7 +59,7 @@ class Counter { } async *readHelloChan(name: string): AsyncIterableIterator { - const hello = this.state.stub(Hello).id(this.state.id); + const hello = this.state.proxy(Hello).id(this.state.id); using helloChan = hello.chan(name); for await (const event of helloChan.recv()) { yield event; @@ -100,10 +100,10 @@ Deno.test("counter tests", async () => { reqCount++; }); const actorId = "1234"; - const counterStub = actors.stub(Counter); + const counterProxy = actors.proxy(Counter); - const counterActor = counterStub.id(actorId); - using rpcActor = counterStub.id("12345", "1234").rpc(); + const counterActor = counterProxy.id(actorId); + using rpcActor = counterProxy.id("12345", "1234").rpc(); for (const actor of [rpcActor, counterActor]) { const name = `Counter Actor`; diff --git a/src/actors/runtime.ts b/src/actors/runtime.ts index 7070844..ec8da20 100644 --- a/src/actors/runtime.ts +++ b/src/actors/runtime.ts @@ -1,6 +1,12 @@ // deno-lint-ignore-file no-explicit-any import process from "node:process"; import { ActorError } from "./errors.ts"; +import { + ACTOR_CONSTRUCTOR_NAME_HEADER, + ACTOR_DISCRIMINATOR_HEADER_NAME, + ACTOR_DISCRIMINATOR_QS_NAME, + ACTOR_ID_HEADER_NAME, +} from "./proxyutil.ts"; import { ActorSilo } from "./silo.ts"; import type { ActorState } from "./state.ts"; import type { ActorStorage } from "./storage.ts"; @@ -10,12 +16,6 @@ import { EVENT_STREAM_RESPONSE_HEADER, isEventStreamResponse, } from "./stream.ts"; -import { - ACTOR_CONSTRUCTOR_NAME_HEADER, - ACTOR_DISCRIMINATOR_HEADER_NAME, - ACTOR_DISCRIMINATOR_QS_NAME, - ACTOR_ID_HEADER_NAME, -} from "./stubutil.ts"; import { serializeUint8Array } from "./util/buffers.ts"; import { isUpgrade, makeWebSocket } from "./util/channels/channel.ts"; import { actorId as getActorId } from "./util/id.ts"; diff --git a/src/actors/runtimes/cf/fetcher.ts b/src/actors/runtimes/cf/fetcher.ts index 87a9fbc..1bb40d1 100644 --- a/src/actors/runtimes/cf/fetcher.ts +++ b/src/actors/runtimes/cf/fetcher.ts @@ -1,6 +1,6 @@ import type { DurableObjectNamespace } from "@cloudflare/workers-types"; +import { ACTOR_ID_HEADER_NAME } from "../../proxyutil.ts"; import type { ActorConstructor, ActorFetcher } from "../../runtime.ts"; -import { ACTOR_ID_HEADER_NAME } from "../../stubutil.ts"; import { actorId as getActorId } from "../../util/id.ts"; import { registerActors } from "./actorDO.ts"; diff --git a/src/actors/silo.ts b/src/actors/silo.ts index 13dee8b..381da6d 100644 --- a/src/actors/silo.ts +++ b/src/actors/silo.ts @@ -1,14 +1,14 @@ import { ActorError } from "./errors.ts"; -import { rpc } from "./rpc.ts"; -import type { ActorConstructor, ActorInstance } from "./runtime.ts"; -import { ActorState } from "./state.ts"; -import type { ActorStorage } from "./storage.ts"; import { type ActorInvoker, create, createHttpInvoker, WELL_KNOWN_RPC_MEHTOD, -} from "./stubutil.ts"; +} from "./proxyutil.ts"; +import { rpc } from "./rpc.ts"; +import type { ActorConstructor, ActorInstance } from "./runtime.ts"; +import { ActorState } from "./state.ts"; +import type { ActorStorage } from "./storage.ts"; import { isUpgrade, makeDuplexChannel } from "./util/channels/channel.ts"; // deno-lint-ignore no-explicit-any type FunctionType = (...args: any) => any; @@ -51,7 +51,7 @@ export class ActorSilo { id: this.actorId, discriminator: this.discriminator, storage, - stub: (actor) => { + proxy: (actor) => { const invoker = (id: string) => { if (id === this.actorId) { return this.invoker; @@ -105,7 +105,7 @@ export class ActorSilo { ); } - const actorStub = new Proxy(actorInstance.actor, { + const actorProxy = new Proxy(actorInstance.actor, { get(target, prop, receiver) { if (prop === "metadata") { return metadata; @@ -116,7 +116,7 @@ export class ActorSilo { // deno-lint-ignore ban-types const result = await (methodImpl as Function).apply( - actorStub, + actorProxy, Array.isArray(args) ? args : [args], ); diff --git a/src/actors/state.ts b/src/actors/state.ts index 502b215..1f789f7 100644 --- a/src/actors/state.ts +++ b/src/actors/state.ts @@ -1,12 +1,12 @@ +import type { create } from "./proxyutil.ts"; import type { Actor, ActorConstructor } from "./runtime.ts"; import type { ActorStorage } from "./storage.ts"; -import type { create } from "./stubutil.ts"; export interface ActorStateOptions { id: string; discriminator?: string; storage: ActorStorage; - stub: ( + proxy: ( actor: ActorConstructor, ) => ReturnType>; } @@ -17,13 +17,13 @@ export class ActorState { public id: string; public discriminator?: string; public storage: ActorStorage; - public stub: ( + public proxy: ( actor: ActorConstructor, ) => ReturnType>; public initialization: Promise = Promise.resolve(); constructor(options: ActorStateOptions) { this.storage = options.storage; - this.stub = options.stub; + this.proxy = options.proxy; this.id = options.id; this.discriminator = options.discriminator; } diff --git a/src/actors/util/id.ts b/src/actors/util/id.ts index 761f3a2..0efbf1d 100644 --- a/src/actors/util/id.ts +++ b/src/actors/util/id.ts @@ -1,4 +1,4 @@ -import { ACTOR_ID_HEADER_NAME, ACTOR_ID_QS_NAME } from "../stubutil.ts"; +import { ACTOR_ID_HEADER_NAME, ACTOR_ID_QS_NAME } from "../proxyutil.ts"; /** * Retrieves the actor ID from the request.