shibuya-pgmq-adapter 0.12.0.0 → 0.13.0.0
raw patch · 5 files changed
+95/−10 lines, 5 filesdep ~pgmq-coredep ~pgmq-effectfuldep ~pgmq-hasqlPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: pgmq-core, pgmq-effectful, pgmq-hasql, pgmq-migration
API changes (from Hackage documentation)
Files
- CHANGELOG.md +32/−0
- shibuya-pgmq-adapter.cabal +8/−8
- src/Shibuya/Adapter/Pgmq/Internal.hs +3/−1
- test/Shibuya/Adapter/Pgmq/ConfigSpec.hs +11/−1
- test/Shibuya/Adapter/Pgmq/IntegrationSpec.hs +41/−0
CHANGELOG.md view
@@ -1,5 +1,37 @@ # Changelog +## 0.13.0.0 — 2026-08-09++Driven by the `pgmq-hs` 0.5 release. The adapter remains paired with+`shibuya-core 0.8.0.1`, and its own public function and record signatures are unchanged.++### Breaking Changes++- Requires `pgmq-core ^>=0.5`, `pgmq-effectful ^>=0.5`, and `pgmq-hasql ^>=0.5` in+ the library, plus `pgmq-migration ^>=0.5` in the test stanza, up from the 0.4 family.+- The re-exported `parseQueueName` now accepts only non-empty names of at most 47+ lowercase ASCII letters, digits, or underscores (`[a-z0-9_]{1,47}`). Operators must+ detect and transactionally remediate mixed-case `pgmq.meta` rows before rollout; see+ [Installing the PGMQ schema](../docs/user/pgmq-getting-started.md#before-upgrading-to-pgmq--05).++### Reliability++- `mkLease` handles pgmq-hs 0.5's `Maybe Message` visibility-timeout result. When a+ message was deleted, archived, or popped before extension reached it, `leaseExtend`+ returns normally and leaves the last confirmed visibility deadline unchanged. A live+ row still advances that deadline from the value PostgreSQL returns.+- The existing bounded retry wrapper inherits pgmq-effectful 0.5's broader transient+ SQLSTATE classification: serialization failures, deadlocks, lock-unavailable errors,+ server shutdown/recovery, and class 53 resource errors are now eligible for retry.+- The test harness and downstream components inherit pgmq-migration 0.5's notification+ crash-safety migration, which fails open after crash recovery truncates the unlogged+ throttle table so insert notifications continue until reconciliation restores it.++### Tests++- Added a PostgreSQL-backed regression for extending a lease after its message is deleted+ and a public-boundary regression for lowercase, uppercase, and empty queue names.+ ## 0.12.0.0 — 2026-07-14 Driven by the `pgmq-hs` 0.4 release. Still paired with `shibuya-core 0.8.0.1`
shibuya-pgmq-adapter.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.12 name: shibuya-pgmq-adapter-version: 0.12.0.0+version: 0.13.0.0 synopsis: PGMQ adapter for the Shibuya queue processing framework description: A Shibuya adapter that integrates with pgmq (PostgreSQL Message Queue)@@ -46,9 +46,9 @@ hasql ^>=1.10, hasql-pool ^>=1.4, hasql-transaction ^>=1.2,- pgmq-core ^>=0.4,- pgmq-effectful ^>=0.4,- pgmq-hasql ^>=0.4,+ pgmq-core ^>=0.5,+ pgmq-effectful ^>=0.5,+ pgmq-hasql ^>=0.5, shibuya-core ^>=0.8.0.1, stm ^>=2.5, streamly ^>=0.11,@@ -113,10 +113,10 @@ hasql-transaction ^>=1.2, hspec ^>=2.11, pg-migrate ^>=1.1,- pgmq-core ^>=0.4,- pgmq-effectful ^>=0.4,- pgmq-hasql ^>=0.4,- pgmq-migration ^>=0.4,+ pgmq-core ^>=0.5,+ pgmq-effectful ^>=0.5,+ pgmq-hasql ^>=0.5,+ pgmq-migration ^>=0.5, quickcheck-instances ^>=0.3, random, shibuya-core ^>=0.8.0.1,
src/Shibuya/Adapter/Pgmq/Internal.hs view
@@ -202,7 +202,9 @@ messageId = msg.messageId, visibilityTime = target }- liftIO $ writeIORef lastVtRef updated.visibilityTime+ case updated of+ Nothing -> pure ()+ Just updatedMessage -> liftIO $ writeIORef lastVtRef updatedMessage.visibilityTime } -- | Create an AckHandle for a message.
test/Shibuya/Adapter/Pgmq/ConfigSpec.hs view
@@ -1,6 +1,8 @@ module Shibuya.Adapter.Pgmq.ConfigSpec (spec) where -import Pgmq.Types (parseQueueName, parseRoutingKey)+import Data.Either (isLeft, isRight)+import Pgmq.Types (parseRoutingKey)+import Shibuya.Adapter.Pgmq (parseQueueName) import Shibuya.Adapter.Pgmq.Config import Test.Hspec @@ -12,6 +14,7 @@ validateConfigSpec deadLetterTargetSpec smartConstructorSpec+ queueNameBoundarySpec -- | Tests for defaultConfig defaultConfigSpec :: Spec@@ -173,3 +176,10 @@ it "sets includeMetadata correctly" $ do let config = topicDeadLetter routingKey False config.includeMetadata `shouldBe` False++queueNameBoundarySpec :: Spec+queueNameBoundarySpec = describe "parseQueueName" $ do+ it "accepts lowercase names and rejects uppercase and empty names" $ do+ parseQueueName "orders" `shouldSatisfy` isRight+ parseQueueName "Orders" `shouldSatisfy` isLeft+ parseQueueName "" `shouldSatisfy` isLeft
test/Shibuya/Adapter/Pgmq/IntegrationSpec.hs view
@@ -26,9 +26,12 @@ import Shibuya.Adapter.Pgmq.Config ( PgmqAdapterConfig (..), PollingConfig (..),+ defaultConfig, defaultPollRetryConfig, ) import Shibuya.Adapter.Pgmq.Convert (pgmqMessageToEnvelope)+import Shibuya.Adapter.Pgmq.Internal (mkLease)+import Shibuya.Core.Lease (Lease (..)) import Shibuya.Core.Types (Envelope (..)) import System.Environment (lookupEnv) import Test.Hspec@@ -236,6 +239,44 @@ } pure $ Vector.length msgs count `shouldBe` 1++ it "lease extension is a no-op after the message is deleted" $ \TestFixture {pool, queueName, dlqName = _} -> do+ runPgmqSession pool $ do+ _ <-+ Sessions.sendMessage $+ SendMessage+ { queueName = queueName,+ messageBody = MessageBody (String "lease-race-test"),+ delay = Just 0+ }+ pure ()++ runAdapterIO pool $ do+ msgs <-+ PgmqEff.readMessage $+ ReadMessage+ { queueName = queueName,+ delay = 30,+ batchSize = Just 1,+ conditional = Nothing+ }+ case Vector.uncons msgs of+ Just (msg, _) -> do+ lease <- mkLease (defaultConfig queueName) msg+ _ <- PgmqEff.deleteMessage (MessageQuery queueName msg.messageId)+ lease.leaseExtend 30+ Nothing -> liftIO $ expectationFailure "Expected one message to construct a lease"++ remaining <-+ runPgmqSession pool $+ Sessions.readMessage $+ ReadMessage+ { queueName = queueName,+ delay = 30,+ batchSize = Just 1,+ conditional = Nothing+ }+ Vector.length remaining `shouldBe` 0 -- | Retry handling tests (simulating AckRetry behavior) retryHandlingSpec :: SpecWith TestFixture