@hackage / shibuya-pgmq-adapter

PGMQ adapter for the Shibuya queue processing framework

Latest0.12.0.0

Changelog

Changelog

0.12.0.0 — 2026-07-14

Driven by the pgmq-hs 0.4 release. Still paired with shibuya-core 0.8.0.1 (unchanged bound).

Breaking Changes
  • Requires the pgmq-* 0.4 package family: pgmq-core ^>=0.4, pgmq-effectful ^>=0.4, and pgmq-hasql ^>=0.4 in the library (plus pgmq-migration ^>=0.4 and pg-migrate ^>=1.1 in the test stanza), up from ^>=0.3.
  • The adapter's own API is unchanged, but consumers that install the PGMQ schema with pgmq-migration must migrate: 0.4 replaced the migrate / upgrade / validate runner with a pg-migrate component. Pgmq.Migration now exports only pgmqMigrations, MigrationComponent, and DefinitionError; an application composes the component into a plan with migrationPlan and runs it with runMigrationPlan, which takes hasql connection settings rather than a Pool or Connection.
  • A database created by pgmq-migration 0.3 or earlier must have its public.schema_migrations ledger imported once via Pgmq.Migration.History.HasqlMigration before the native runner takes over — the native runner keeps its own ledger and does not read the old table. See Installing the PGMQ schema.
Bug Fixes
  • Idle streams now observe shutdown. The shutdown gate was checked only after empty poll chunks were filtered out, so a processor with nothing to consume kept polling until it was forcibly cancelled instead of finishing on request. The gate is now checked before the empty-chunk filter, covered by a PostgreSQL lifecycle regression test.

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