Skip to content

post

Post rejected an unknown route or conflicting key.

  • YieldableError<this> & object & Readonly<{ message: string; }>

new PostError(message): PostError

string

PostError

Data.TaggedError("PostError")<{ readonly message: string; }>.constructor

message: string

Data.TaggedError("PostError").message

PostDeliveryResult = "accepted" | "duplicate" | "refused" | Readonly<{ status: "accepted" | "duplicate"; cursor: number; }> | Readonly<{ status: "accepted" | "duplicate" | "refused"; receipt: Schema.Json; }>

Receiver’s idempotent admission decision.


PostOutboxStore<E> > = Readonly<{ put: (key, value) => Effect.Effect<void, E>>; read: (key) => Effect.Effect<string | undefined, E>>; list: (limit, afterKey?) => Effect.Effect<readonly Readonly<{ key: string; value: string; }>[], E>>; delete: (key) => Effect.Effect<void, E>>; }>

Durable, string-backed rows. A delivered receipt must outlive source replay.

E


PostOutbox<M, E> > = Readonly<{ enqueue: (message, at?) => Effect.Effect<number | undefined, E>>; drain: () => Effect.Effect<void, E>>; deadLetters: (limit, afterKey?) => Effect.Effect<M[], E>>; }>

Bounded generic delivery owned by Post.

M

E


PostEnvelope = Schema.Schema.Type<typeof PostEnvelopeSchema>>

One addressed event identified by the producer’s stable key.


PostRow = Schema.Schema.Type<typeof PostRowSchema>>

Pending row, terminal receipt, or dead letter.


PostRoute<A, E, D, AI, EI, DI> > = Readonly<{ addressKind: string; address: Schema.Codec<A, AI>>; event: Schema.Codec<E, EI>>; name: (address) => string; namespace: Readonly<{ getByName: (name) => Readonly<{ deliver: (envelope) => Promise<PostDeliveryResult>>; }>; }>; }> & Readonly<{ prepare: Readonly<{ event: Schema.Codec<D, DI>>; run: (address, intent, signal) => Promise<D>>; }>; onDelivered?: (address, event) => void; onCursor?: (address, event, cursor) => void; onRefused?: (address, event) => void; }> | Readonly<{ prepare?: undefined; onDelivered?: (address, event) => void; onCursor?: (address, event, cursor) => void; onRefused?: (address, event) => void; }>

Schema-correlated ordinary events or prepared delivery facts.

A

E

D = E

AI = A

EI = E

DI = EI


PostRegistryRoute = Readonly<{ addressKind: string; address: Schema.Codec<unknown, unknown>>; event: Schema.Codec<unknown, unknown>>; encodeEnvelope: (envelope) => PostEnvelope; parseDelivery: (envelope) => PostEnvelope; prepareEnvelope?: (envelope, signal) => Promise<PostEnvelope>>; recordDelivered?: (envelope) => void; nameOf: (envelope) => string; namespace: PostRoute<never, never>>["namespace"]; recordCursor?: (envelope, cursor) => void; recordRefused?: (envelope) => void; }>

Runtime operations that preserve the route’s schema evidence.


PostRuntime<R> > = Readonly<{ send: <K>>(input) => void; execute: (job) => Promise<Readonly<{ kind: "completed"; }>>; enqueueDue: (limit?, afterKey?) => Promise<string | undefined>>; deadLetters: (limit?, afterKey?) => Readonly<{ letters: readonly Readonly<{ key: string; reason: "refused" | "exhausted"; envelope: PostEnvelope; attempts: number; }>[]; nextCursor: string | undefined; }>; latest: <K>>(kind, address) => Readonly<{ key: string; row: PostRow; }> | undefined; retry: (key) => Promise<void>>; read: (key) => PostRow | undefined; nextWake: () => number | null; }>

One producer’s Post operations.

R extends Record<string, PostRegistryRoute>

const PostDeliveryResultSchema: Union<readonly [Literals<readonly ["accepted", "duplicate", "refused"]>, Struct<{ status: Literals<readonly ["accepted", "duplicate"]>; cursor: Int; }>, Struct<{ status: Literals<readonly ["accepted", "duplicate", "refused"]>; receipt: Codec<Json, Json, never, never>>; }>]>

Accepted receipt, revision cursor, or permanent refusal returned by a receiver.


const PostEnvelopeSchema: Struct<{ key: String; kind: String; address: Unknown; event: Unknown; }>

Wire envelope parsed at the durable row and receiver boundaries.


const PostRowSchema: fromJsonString<Union<readonly [Struct<{ state: Literal<"pending">>; envelope: Struct<{ key: String; kind: String; address: Unknown; event: Unknown; }>; attempts: Int; nextAttemptAt: Number; jobId: optional<String>>; delivery: optional<Struct<{ key: String; kind: String; address: Unknown; event: Unknown; }>>; nextKey: optional<String>>; }>, Struct<{ state: Literal<"delivered">>; receipt: optional<Codec<Json, Json, never, never>>>>; nextKey: optional<String>>; }>, Struct<{ state: Literal<"dead">>; envelope: Struct<{ key: String; kind: String; address: Unknown; event: Unknown; }>; attempts: Int; reason: Literals<readonly ["refused", "exhausted"]>; receipt: optional<Codec<Json, Json, never, never>>>>; delivery: optional<Struct<{ key: String; kind: String; address: Unknown; event: Unknown; }>>; nextKey: optional<String>>; }>]>>

Persisted Post row parser.

retryDelay(attempts): number

BirdDog’s retained bounded retry schedule.

number

number


makePostOutbox<M, E>>(options): PostOutbox<M, E>>

The same bounded delivery and receipt machinery serves Post and BirdDog.

M

E

Readonly<{ message: Schema.Codec<M>; key: (message) => string; outbox: PostOutboxStore<E>; deliver: (message) => Effect.Effect<boolean, E>; scheduleWake: (at) => Effect.Effect<void, E>; now: () => number; invalidRow: () => E; encodingFailed: () => E; }>

PostOutbox<M, E>


definePostRoute<A, E, AI, EI>>(route): PostRoute<A, E, E, AI, EI, EI> > & Omit<Readonly<{ addressKind: string; address: Codec<unknown, unknown>>; event: Codec<unknown, unknown>>; encodeEnvelope: (envelope) => object; parseDelivery: (envelope) => object; prepareEnvelope?: (envelope, signal) => Promise<{ key: string; kind: string; address: unknown; event: unknown; }>; recordDelivered?: (envelope) => void; nameOf: (envelope) => string; namespace: Readonly<{ getByName: (name) => Readonly<{ deliver: (envelope) => Promise<…>; }>; }>; recordCursor?: (envelope, cursor) => void; recordRefused?: (envelope) => void; }>, "address" | "event">>

Preserve each route’s inferred address and event types in a registry.

A

E

AI = A

EI = E

Readonly<{ addressKind: string; address: Codec<A, AI>; event: Codec<E, EI>; name: (address) => string; namespace: Readonly<{ getByName: (name) => Readonly<{ deliver: (envelope) => Promise<PostDeliveryResult>; }>; }>; }> & Readonly<{ prepare?: undefined; onDelivered?: (address, event) => void; onCursor?: (address, event, cursor) => void; onRefused?: (address, event) => void; }>

PostRoute<A, E, E, AI, EI, EI> & Omit<Readonly<{ addressKind: string; address: Codec<unknown, unknown>; event: Codec<unknown, unknown>; encodeEnvelope: (envelope) => object; parseDelivery: (envelope) => object; prepareEnvelope?: (envelope, signal) => Promise<{ key: string; kind: string; address: unknown; event: unknown; }>; recordDelivered?: (envelope) => void; nameOf: (envelope) => string; namespace: Readonly<{ getByName: (name) => Readonly<{ deliver: (envelope) => Promise<…>; }>; }>; recordCursor?: (envelope, cursor) => void; recordRefused?: (envelope) => void; }>, "address" | "event">

definePostRoute<A, E, D, AI, EI, DI>>(route): PostRoute<A, E, D, AI, EI, DI> > & Omit<Readonly<{ addressKind: string; address: Codec<unknown, unknown>>; event: Codec<unknown, unknown>>; encodeEnvelope: (envelope) => object; parseDelivery: (envelope) => object; prepareEnvelope?: (envelope, signal) => Promise<{ key: string; kind: string; address: unknown; event: unknown; }>; recordDelivered?: (envelope) => void; nameOf: (envelope) => string; namespace: Readonly<{ getByName: (name) => Readonly<{ deliver: (envelope) => Promise<…>; }>; }>; recordCursor?: (envelope, cursor) => void; recordRefused?: (envelope) => void; }>, "address" | "event">>

Preserve each route’s inferred address and event types in a registry.

A

E

D

AI = A

EI = E

DI = EI

Readonly<{ addressKind: string; address: Codec<A, AI>; event: Codec<E, EI>; name: (address) => string; namespace: Readonly<{ getByName: (name) => Readonly<{ deliver: (envelope) => Promise<PostDeliveryResult>; }>; }>; }> & Readonly<{ prepare: Readonly<{ event: Schema.Codec<D, DI>; run: (address, intent, signal) => Promise<D>; }>; onDelivered?: (address, event) => void; onCursor?: (address, event, cursor) => void; onRefused?: (address, event) => void; }>

PostRoute<A, E, D, AI, EI, DI> & Omit<Readonly<{ addressKind: string; address: Codec<unknown, unknown>; event: Codec<unknown, unknown>; encodeEnvelope: (envelope) => object; parseDelivery: (envelope) => object; prepareEnvelope?: (envelope, signal) => Promise<{ key: string; kind: string; address: unknown; event: unknown; }>; recordDelivered?: (envelope) => void; nameOf: (envelope) => string; namespace: Readonly<{ getByName: (name) => Readonly<{ deliver: (envelope) => Promise<…>; }>; }>; recordCursor?: (envelope, cursor) => void; recordRefused?: (envelope) => void; }>, "address" | "event">


createPost<R>>(options): PostRuntime<R>>

Decode at both persisted and DO boundaries with the route’s Effect Schema.

R extends Record<string, Readonly<{ addressKind: string; address: Codec<unknown, unknown>; event: Codec<unknown, unknown>; encodeEnvelope: (envelope) => object; parseDelivery: (envelope) => object; prepareEnvelope?: (envelope, signal) => Promise<{ key: string; kind: string; address: unknown; event: unknown; }>; recordDelivered?: (envelope) => void; nameOf: (envelope) => string; namespace: Readonly<{ getByName: (name) => Readonly<{ deliver: (envelope) => Promise<PostDeliveryResult>; }>; }>; recordCursor?: (envelope, cursor) => void; recordRefused?: (envelope) => void; }>>

Readonly<{ routes: R; owner: WatchdogSqliteOwner; transactional: WatchdogTransactionalProjection; readJob: WatchdogRuntime["read"]; now: () => number; scheduleWake: (at) => Promise<void>; }>

PostRuntime<R>


admitPost<E, I>>(options): PostDeliveryResult

Consumer admission runs inside the receiver’s own SQLite transaction.

E

I

Readonly<{ key: string; event: unknown; schema: Schema.Codec<E, I>; hasReceipt: (key) => boolean; apply: (event) => PostDeliveryResult; putReceipt: (key) => void; }>

PostDeliveryResult