Actors/Packages/Cloudflare/API reference
@sigx/actors-cloudflare · Preview

API reference#

Exports of @sigx/actors-cloudflare v0.1.0.

Assembled entries#

Most apps use these two rather than the seams below.

createHostDurableObject<Env>(options)#

Returns a class to extend. The object hosts exactly the actor its id names.

TypeScript
interface HostDurableObjectOptions<Env> {
    actors?: AnyActorDefinition[];
    namespace(env: Env): DurableObjectNamespaceLike;
    app?(base: DurableAppOptions): ActorApp;
    placement?: Pick<DurableObjectPlacementOptions,
        'objectName' | 'locationHint' | 'jurisdiction' | 'base'>;
    endpoint?: HostEndpointOptions;
}

The instance exposes fetch(request), alarm() and host(): Promise<Host>.

The app factory receives the object's own storage, reminders and defaults and must pass them on. It never receives env, so it cannot reach a namespace binding and build a placement of its own.

createWorkerHandler<Env>(options)#

The edge. Hosts nothing, routes everything. Same options minus endpoint, plus fetch?: FetchHandlerOptions.

Seams#

ExportRole
durableObjectStorage(storage, options?)ActorStorage on DO storage
durableObjectReminders(options)ActorReminders on the DO alarm
durableObjectPlacement(options?)routes a ref to its object
durableObjects(options?)the placement as a plugin
durableObjectName(...)the ref → object-name function
unhostedStorage()storage for the Worker half, which hosts nothing

Placement runs on both sides#

TypeScript
// inside the object
durableObjectPlacement({ isSelf: (ref) => actorId(ref) === state.id.name });
// in the Worker — no isSelf; everything is remote
durableObjectPlacement();

Using the plain local host inside an object silently corrupts state: a cross-actor call would activate the callee inside the caller's object, writing its record into the wrong storage and violating single activation. See Cloudflare Workers.

locationHint is a hint and safe to change. jurisdiction and objectName are part of identity, so changing either is a state migration.

Alarm concurrency#

onAlarm() runs in three phases and does not hold blockConcurrencyWhile across delivery: claim and persist (gated) → deliver (ungated) → re-read and re-arm (gated).

Holding the gate across delivery deadlocked the object, because rescheduling from inside onReminder takes the gate itself and blockConcurrencyWhile does not nest.

Relatedly, an expected failure — the wrong-owner error from ctx.reminders.set() — is returned as a value and thrown after the gate closes. An exception escaping blockConcurrencyWhile resets the Durable Object.

Types#

DurableObjectIdLike, DurableObjectNamespaceLike, DurableObjectStubLike, DurableObjectStorageOptions, DurableObjectRemindersOptions, DurableObjectPlacementOptions, DurableAppOptions, DurableObjectStateLike, HostDurableObjectInstance, WorkerHandler, WorkerHandlerOptions, BlockConcurrencyWhile, DurableStorage, DurableAlarms.

Next steps#