packages feed

shibuya-pgmq-adapter-0.11.0.0: CHANGELOG.md

# Changelog

## 0.11.0.0 — 2026-07-04

Paired with `shibuya-core 0.8.0.1`.

### Breaking Changes

- Requires `shibuya-core ^>=0.8.0.1` (up from `^>=0.7.0.0`) in the library and
  test stanzas. `shibuya-core 0.8.0.0` is a breaking release, so adapter
  consumers must migrate along with it:
  - Handlers now receive `Message es msg` (envelope + optional lease, no ack
    finalizer) instead of `Ingested`. Handlers written against the `Handler`
    type alias that read `msg.envelope` / `msg.lease` compile unchanged;
    handlers with an explicit `Ingested es msg -> …` signature must switch to
    `Message es msg -> …`.
  - `runApp` now takes a validated `AppConfig` record instead of positional
    supervision-strategy and inbox-size arguments. `defaultAppConfig`
    (`AppConfig { strategy = IgnoreFailures, inboxSize = 100 }`) is the drop-in
    replacement for the old `runApp IgnoreFailures 100 …`.
  - The runner internals moved under `Shibuya.Internal.*`; metrics types such as
    `ProcessorId` are public via `Shibuya.Core.Metrics` (and re-exported from
    `Shibuya.App`).

  See the `shibuya-core 0.8.0.0` migration guide for the full list.

### Notes

- The `^>=0.8.0.1` lower bound (rather than `0.8.0.0`) pulls in the
  `shibuya-core 0.8.0.1` patch, which cuts per-message allocation on the `Async`
  and `Ahead` concurrency dispatch paths. No API or behavior change; it benefits
  the adapter's throughput on those paths for free.
- The adapter's own public API is unchanged. `pgmqSource` still yields
  `Ingested es Value`; the framework projects each `Ingested` to the
  handler-facing `Message` itself.
- The bundled example (`shibuya-pgmq-example`) and benchmark
  (`shibuya-pgmq-adapter-bench`), plus the README and getting-started guide,
  were updated to the `shibuya-core 0.8.0.0` API (`runApp defaultAppConfig`, the
  `Message` handler pattern, `ProcessorId` from `Shibuya.App`). Neither the
  example nor the benchmark is published to Hackage.

## 0.10.0.0 — 2026-07-04

### Features

- Reintroduced opt-in concurrent prefetch via `prefetchConfig :: Maybe PrefetchConfig`
  (default `Nothing`). When enabled, the polling stage reads the next batches on a
  background worker, overlapping database latency with handler work. The historical
  `parBuffered` deadlock (`thread blocked indefinitely in an STM transaction`) is fixed
  by running only the prefetch stage under effectful's `ConcUnlift` strategy (scoped via
  `morphInner`), so the non-prefetch path is unchanged (still `SeqUnlift`, no overhead).

### Breaking Changes

- `PgmqAdapterConfig` gained a `prefetchConfig :: Maybe PrefetchConfig` field. Callers that
  construct the config by full record literal must add it; `defaultConfig` sets it to `Nothing`.
- `PgmqConfigError` gained an `InvalidPrefetchBufferSize` constructor; `validateConfig` now
  rejects a prefetch `bufferSize` of `0`.

### Notes

- Shutdown with prefetch enabled can leave up to `bufferSize * batchSize` already-read
  messages invisible until their visibility timeout expires. No messages are lost — they are
  redelivered after the visibility timeout; only redelivery is delayed. This bounded,
  at-least-once-safe behaviour is documented on `PrefetchConfig` and in the adapter
  architecture docs.

## 0.9.0.0 — 2026-07-02

### Breaking Changes

- `pgmqAdapter` now takes `PgmqAdapterEnv` and returns `Either PgmqConfigError (Adapter es Value)`.
- `PgmqAdapterConfig` gained `ackRetry` and `haltVisibilityTimeout`, and removed the known-deadlocking concurrent lookahead configuration.

### Reliability

- DLQ send and source delete now run in one PostgreSQL transaction.
- Message finalizers are idempotent after success.
- Ack operations and lease extension use bounded transient retry.
- `AckHalt` uses a configured visibility timeout instead of a hardcoded hour.
- Lease extension uses absolute visibility deadlines so later extension calls do not shorten the tracked lease.
- Trace header merging on the DLQ path tolerates non-UTF8 bytes.

## 0.8.0.0 — 2026-06-15

### Breaking Changes

- `PgmqAdapterConfig` gained a `pollRetry :: PollRetryConfig` field. Callers
  that construct the config by record literal must add it (or start from a
  smart constructor / default that includes it).
- `pgmqAdapter` now requires `Error PgmqRuntimeError :> es` in its effect row
  so transient poll errors can be caught and retried before being rethrown.

### Bug Fixes

- Transient PGMQ poll errors are retried with bounded exponential backoff
  before the adapter gives up. The default policy makes five total attempts,
  starting at 100ms and capping at five seconds. Permanent errors and
  exhausted retry budgets still surface to shibuya supervision.

## 0.7.0.0 — 2026-06-05

Paired with `shibuya-core 0.7.0.0`.

### Breaking Changes

- Tracks the new `Envelope.headers :: Maybe Headers` field added in
  `shibuya-core 0.7.0.0`. `pgmqMessageToEnvelope` sets it to `Nothing`:
  pgmq does not deliver an ordered, duplicate-allowing raw broker-header
  stream. The per-message JSONB `headers` object is unordered user
  metadata and is consumed only to derive `partition` and
  `traceContext`, so it is deliberately not re-presented as broker
  headers. Callers that construct `Envelope` by record literal (e.g.
  test fixtures) must add `headers = Nothing`. A `Future:` note in
  `Shibuya.Adapter.Pgmq.Convert` records the option of surfacing
  producer-supplied pgmq headers later — deferred because the JSONB
  object's unordered, unique-key shape maps lossily onto the ordered,
  duplicate-allowing `Headers` type.

### Compatibility

- Requires `shibuya-core ^>=0.7.0.0` for the `headers` field on
  `Envelope`. The bound is bumped in the library and test stanzas.
- Lowers `cabal-version` from `3.14` to `3.12` so Nix toolchains with an
  older bundled Cabal can build the adapter. No package-description
  syntax requiring 3.14 was in use.

### Tests

- `Shibuya.Adapter.Pgmq.ConvertSpec` gains two cases asserting `headers`
  is `Nothing`, including one where the pgmq JSONB `headers` object is
  non-empty.

## 0.6.0.0 — 2026-05-31

Paired with `shibuya-core 0.6.0.0`.

### Compatibility

- Upgrades the adapter package to the current dependency family:
  `shibuya-core ^>=0.6.0.0`, `pgmq-core ^>=0.3`,
  `pgmq-hasql ^>=0.3`, `pgmq-effectful ^>=0.3`, and
  test-only `pgmq-migration ^>=0.3`.
- No adapter API changes were required. `pgmqAdapter` and the
  `Envelope` conversion behavior remain the same.

### OpenTelemetry

- Shibuya processor spans now use the stable
  `messaging.operation.type = "process"` key from
  `shibuya-core 0.6.0.0`.
- PGMQ operation spans are provided by `pgmq-effectful 0.3.0.0`, which
  builds on `hs-opentelemetry` 1.0 and supports old, stable, or
  duplicate messaging/database semantic-convention attributes via
  `OTEL_SEMCONV_STABILITY_OPT_IN`.

## 0.4.0.0 — 2026-04-29

Paired with `shibuya-core 0.4.0.0`.

### Additions

- Envelopes now carry the delivery `attempt` counter (from pgmq's
  `readCount`, zero-indexed), enabling exponential backoff via
  `Shibuya.Core.Retry`. The first delivery sees `Just (Attempt 0)`, the
  first retry `Just (Attempt 1)`, and so on.

### Internal

- `nominalToSeconds` (in `Shibuya.Adapter.Pgmq.Internal`) now clamps to
  the `Int32` range instead of silently wrapping. Misconfigured
  retry/lease durations cap at ~68 years rather than producing
  undefined behavior on the visibility-timeout offset passed to pgmq.

### Compatibility

- Requires `shibuya-core ^>=0.4.0.0` for the `Attempt` type and the
  `attempt` field on `Envelope`.

## 0.3.0.0 — 2026-04-24

Upgraded to `pgmq-hs` 0.2.0.0 series
(`pgmq-core`, `pgmq-hasql`, `pgmq-effectful`, `pgmq-migration`
all at `0.2.0.0`).

### Breaking Changes

- Consumers that pin the `Pgmq.Effectful.PgmqError` name in their own
  `runError` / `runErrorNoCallStack` stack must migrate to
  `PgmqRuntimeError`. The old type is still re-exported as a
  deprecated alias for one release.
- Spans emitted by the traced interpreter now follow OpenTelemetry
  semantic-conventions v1.24. Span names (`"publish my-queue"`,
  `"receive my-queue"`) and attribute keys (`messaging.operation`,
  `messaging.system`, `messaging.destination.name`) have changed.
  Dashboards and alerts keyed on the old names will need updating.
- Callers of `Pgmq.Effectful.Traced.sendMessageTraced` must pass an
  `OpenTelemetry.Trace.TracerProvider` instead of an
  `OpenTelemetry.Trace.Tracer`. If you only have a `Tracer` in scope,
  use `OpenTelemetry.Trace.Core.getTracerTracerProvider` to derive the
  provider.

### Other Changes

- No user-visible changes to `shibuya-pgmq-adapter`'s own API.

## 0.2.0.0 — 2026-04-22

Version bumped to track `shibuya-core` 0.2.0.0. No user-visible changes
to `shibuya-pgmq-adapter` itself.

## 0.1.0.0 — 2026-02-24

Initial release.

### New Features

- PGMQ adapter for PostgreSQL message queue integration
- Visibility timeout-based leasing with automatic retry handling
- Optional dead-letter queue support
- Configurable prefetching via PrefetchConfig
- Concurrent prefetching with streamly parBuffered
- OpenTelemetry trace context propagation
- Topic routing support (pgmq-hs 0.1.1.0)
- Comprehensive test suite with property-based and integration tests

### Bug Fixes

- Fix batch wastage using streamly unfoldEach