quasar_postgres
Optional cluster-coordinated PostgreSQL Store for Quasar.
Requires quasar_jobs >= 0.1.0 and < 0.2.0.
See Store contract and ownership and publishing prerequisites.
Migrations in priv/NNN_name.sql are loaded and applied strictly in version
order. Regular migrations run in individual transactions protected by a
PostgreSQL advisory lock. Files whose names begin with NNN_online_ run outside
a transaction, on one checked-out connection protected by the same advisory
lock; this supports PostgreSQL operations such as CREATE INDEX CONCURRENTLY.
Applied versions are recorded in
quasar_jobs_migrations, so concurrent application startup is safe and repeated
calls are idempotent. Migration files must be included in the published package.
Never edit an applied migration; add the next numbered file.
Retention
Retention policy lives in quasar_jobs/retention; this adapter only owns the
PostgreSQL execution strategy:
import quasar_jobs/retention
import quasar_postgres/retention as postgres_retention
let policy =
retention.new()
|> retention.completed_for(days: 7)
|> retention.cancelled_for(days: 30)
|> retention.discarded_for(days: 30)
let assert Ok(cleaner) =
postgres_retention.new(connection, policy)
|> postgres_retention.with_batch_size(rows: 1000)
|> postgres_retention.with_pause(milliseconds: 100)
|> postgres_retention.with_interval(milliseconds: 60_000)
|> postgres_retention.start
The linked cleaner deletes one bounded batch at a time with
FOR UPDATE SKIP LOCKED, pauses cooperatively between batches, and uses a
non-blocking PostgreSQL advisory lock to avoid overlapping delete transactions.
Configure with_reporter to observe rows deleted, duration, failures, and cycle
completion. Call postgres_retention.stop(cleaner) before closing the Pog pool.
Retention removes the job row. Application tables that reference
quasar_jobs(id) must either use ON DELETE CASCADE, remove their data first,
or archive it outside the retention transaction.