API reference
Exports of @sigx/actors-pg v0.7.0.
Providers
| Export | Returns | Role |
|---|---|---|
pgCluster(options) | ClusterProviders | membership + directory |
pgMembership(pool, options?) | ClusterMembership | liveness on the database clock |
pgDirectory(pool, options?) | ActorDirectory | single-activation claims |
pgStorage(options) | ActorStorage | etag-CAS text rows |
pgReminders(options) | ActorReminders | SKIP LOCKED durable reminders |
Schema helpers
// ensurePgSchema(pool: PgPoolLike, options?: { schema?: string }): Promise<void>
// pgSchemaSql(schema?: string): string
await ensurePgSchema(pool); // issues the DDL under an advisory xact lock
await ensurePgSchema(pool, { schema: 'app' });
console.log(pgSchemaSql()); // returns it, for your migration tool
Encoding helpers
pgText(value) and pgTextDecode(value) — the text encoding used for stored values, exported
for tooling that needs to read or write the tables directly.
Types
PgQueryable, PgPoolLike, PgClusterOptions, PgStorageOptions, PgRemindersOptions.
Table layout
All under the configured schema, sigx by default.
state(type, key, etag, state) -- state is text
directory(actor_id, host_id, activation_id) -- + directory_host_id index
hosts(host_id, descriptor, expires_at)
membership_version(id, version)
reminders(type, key, name, next_due, period_ms) -- + reminders_due index
Semantics worth knowing
Etags are client-minted UUIDs, equality-compared only. Every CAS is a single statement whose row count is the verdict — no transactions, no advisory locks.
State is text, not jsonb — deliberately. Actor state may contain NUL, which jsonb
rejects outright, so the column stores the encoded string verbatim and Postgres never parses
it. A top-level array state therefore cannot be silently coerced into a Postgres ARRAY
either.
Directory entries carry no TTL. There is one heartbeat per host, not per activation; entry validity is the owner's liveness in the membership view, and the storage etag CAS remains the integrity floor underneath.
Membership change detection compares host signatures, not just the version counter — a host that dies silently expires on the database clock without anyone bumping a version, and views still converge.
Push is best-effort. LISTEN rides a connection checked out of the pool; if the pool
cannot dedicate one, or the connection drops, the poll is the guarantee and pollMs is the
propagation bound.
Reminders commit before delivery. The advance-or-delete is committed before the handler runs, which is what makes delivery at-most-once and prevents catch-up bursts after an outage.
Next steps
- Overview — what each provider is for.
- Installation — schema and wiring.
- Storage — the seam and the alternatives.
