Actors/Packages/Postgres/API reference
@sigx/actors-pg · Preview

API reference#

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

Providers#

ExportReturnsRole
pgCluster(options)ClusterProvidersmembership + directory
pgMembership(pool, options?)ClusterMembershipliveness on the database clock
pgDirectory(pool, options?)ActorDirectorysingle-activation claims
pgStorage(options)ActorStorageetag-CAS jsonb rows
pgReminders(options)ActorRemindersSKIP LOCKED durable reminders

Schema helpers#

TypeScript
// ensurePgSchema(pool: PgPoolLike, options?: { schema?: string }): Promise<void>
// pgSchemaSql(schema?: string): string

await ensurePgSchema(pool);                  // issues the DDL — dev and tests
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.

SQL
state(type, key, etag, state)                       -- jsonb
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 jsonb, always bound as a JSON string with an explicit cast, so a top-level array state cannot be silently coerced into a Postgres ARRAY.

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#