packages feed

pgmq-config-0.5.0.0: CHANGELOG.md

# Revision history for pgmq-config

## 0.5.0.0 -- 2026-08-06

The reconciler told three lies about what it had done, and could be taken down at startup
by a queue it does not manage. This release fixes all four and states the real contract.

### Breaking Changes

* `ReconcileAction` gains two constructors, and one existing constructor becomes
  reachable. Exhaustive matchers and consumers that count skips need updating.
  * `UpdatedNotifyThrottle !QueueName !Int32 !Int32` — the declared throttle interval
    differed from the stored row and was applied. Fields: queue, observed, declared.
  * `DetectedQueueTypeDrift !QueueName !QueueType !ObservedQueueType` — the queue's
    observed shape contradicts the declared one. This replaces `SkippedQueue` for the
    queue it concerns, so the report still carries exactly one queue-existence action per
    declared config.
  * `SkippedFifoIndex` was unreachable dead code and is now actually emitted.

### New Features

* `ObservedQueueType` (`ObservedStandard`, `ObservedUnlogged`, `ObservedPartitioned`) —
  the three-way queue shape `pgmq.list_queues()` actually reports.
* `defaultThrottleMs :: Int32` — the 250 ms interval pgmq applies when none is given. A
  `NotifyConfig` whose `throttleMs` is `Nothing` means "use this value".

### Bug Fixes

* A queue created by another client under a name `parseQueueName` rejects no longer fails
  your application's startup. `ensureQueues` snapshotted existing queues through the typed
  `listQueues`, whose decoder re-validates every name read back, so one foreign row — say
  `billing-events` — made reconciliation throw at boot. Someone else's queue became your
  boot failure. It now snapshots through `listQueuesUnvalidated` and matches declared
  names textually; foreign rows are simply queues it does not manage, consistent with its
  additive contract.
* `CreatedFifoIndex` is no longer reported when no index was created. The reconciler
  called `create_fifo_index` unconditionally and always reported creation. It now consults
  a `pg_indexes` snapshot, skips the call when the index is present, and reports which of
  the two happened.
* A declared notify throttle that differs from the stored row is now applied instead of
  silently ignored. The snapshot kept only queue names, so drift was invisible. It now
  carries intervals, and a difference is written via `pgmq.update_notify_insert` and
  reported as `UpdatedNotifyThrottle`. `Nothing` and a stored 250 compare equal, so a
  defaulted config does not flap, and an unchanged interval is still left strictly alone
  rather than re-enabled — re-enabling resets `last_notified_at`.
* A declared queue type contradicting the live queue is now reported as
  `DetectedQueueTypeDrift` rather than the misleading `SkippedQueue`. Nothing is mutated:
  converting a queue's type means dropping and recreating it, destroying its messages,
  which a startup reconciler must never do. Partition interval and retention are not
  drift-checked, because `pgmq.list_queues` does not report them.
* `withNotifyInsert Nothing` no longer fails reconciliation on every startup. It reached
  `pgmq.enable_notify_insert` as a SQL NULL throttle, raising SQLSTATE 23502; since
  reconciliation is not one transaction, this failed application startup repeatedly and
  permanently for any config using the default throttle. Fixed in the pgmq-hasql
  statement, which now coalesces to 250 ms.

### Documentation

* The package promised to "ensure all queues exist with the desired settings" and that
  "all operations are idempotent", neither of which described what the reconciler does.
  `ensureQueues`' Haddock is now the canonical statement of the contract: additive
  reconciliation, one documented mutation of existing state (throttle drift, with its
  `last_notified_at` side effect named), queue-type drift reported rather than repaired,
  partition settings deliberately unchecked, and the concurrent multi-replica caveat —
  SQLSTATE 42710 on stock upstream 1.11.0 extension installs, race-free on pgmq-migration
  installs via migration `0003`. `ensureQueuesReport` and both `Eff` twins point at that
  one description so the four copies cannot drift. Haddock coverage on the public modules
  is now 100%. The rationale is in `docs/design/018-reconciliation-contract.md`.

### Other Changes

* The duplicated `Session` and `Effectful` reconciliation logic is now a single
  backend-agnostic core in the internal `Pgmq.Config.Reconcile` module, parameterized over
  a `ReconcileOps` record; the public modules are thin adapters over it.
* Bumped `pgmq-core`, `pgmq-hasql`, and `pgmq-effectful` dependency bounds to
  `>=0.5 && <0.6`.

## 0.4.0.1 -- 2026-07-14

* Version bump only — coordinated release with pgmq-migration 0.4.0.1.
  No source-level changes since 0.4.0.0.

## 0.4.0.0 -- 2026-07-14

* Version bump only — coordinated release with pgmq-migration 0.4.0.0.
  No library source changes since 0.3.0.0; the test suite was updated for the
  native `pgmq-migration` API.
* Bumped `pgmq-core`, `pgmq-hasql`, and `pgmq-effectful` dependency
  bounds to `>=0.4 && <0.5`.

## 0.3.0.0 -- 2026-05-31

* Version bump only — coordinated release with pgmq-effectful 0.3.0.0.
  No source-level changes since 0.2.0.0.
* Bumped `pgmq-core`, `pgmq-hasql`, and `pgmq-effectful` dependency
  bounds to `>=0.3 && <0.4`.

## 0.2.0.0 -- 2026-04-23

Version unified with the rest of the pgmq-hs packages; no pgmq-config
0.1.4.0 was published to Hackage.

### Bug Fixes

* `ensureQueues` and `ensureQueuesEff` are now truly idempotent. Previously they
  issued `pgmq.create`, `pgmq.enable_notify_insert`, `pgmq.create_fifo_index`, and
  `pgmq.bind_topic` unconditionally on every call, which worked by accident for
  standard/unlogged queues but caused trigger recreation on every boot and failed outright
  for partitioned queues (because `pg_partman.create_parent` raises on re-registration).
  Both entry points now route through the existing state-checking reconciliation path.

## 0.1.3.0 -- 2026-03-12

* Initial release
* Declarative queue configuration DSL (QueueConfig, QueueType, etc.)
* Smart constructors: standardQueue, unloggedQueue, partitionedQueue
* Modifiers: withNotifyInsert, withFifoIndex, withTopicBinding
* Reconciliation: ensureQueues, ensureQueuesWithPool, ensureQueuesReport
* Optional effectful integration (behind flag)