packages feed

hasql-1.9.3.2: hspec/Hasql/ConcurrencySpec.hs

module Hasql.ConcurrencySpec (spec) where

import Control.Concurrent
import Hasql.Connection qualified as Connection
import Hasql.Decoders qualified as Decoders
import Hasql.Encoders qualified as Encoders
import Hasql.Session qualified as Session
import Hasql.Statement qualified as Statement
import Hasql.TestingKit.Testcontainers qualified as Testcontainers
import Test.Hspec
import Prelude

spec :: Spec
spec = aroundAll Testcontainers.withConnection do
  describe "Concurrency" do
    it "handles concurrent connections properly" \_ -> do
      -- We need two separate connections for this test
      Testcontainers.withConnectionSettings \settings -> do
        connection1 <- Connection.acquire settings >>= either (fail . show) return
        connection2 <- Connection.acquire settings >>= either (fail . show) return

        let selectSleep =
              Statement.Statement
                "select pg_sleep($1)"
                (Encoders.param (Encoders.nonNullable Encoders.float8))
                Decoders.noResult
                True

        beginVar <- newEmptyMVar
        finishVar <- newEmptyMVar

        _ <- forkIO do
          putMVar beginVar ()
          _ <- Session.run (Session.statement (0.2 :: Double) selectSleep) connection1
          void (tryPutMVar finishVar False)

        _ <- forkIO do
          takeMVar beginVar
          _ <- Session.run (Session.statement (0.1 :: Double) selectSleep) connection2
          void (tryPutMVar finishVar True)

        -- The second connection should finish first (True)
        result <- takeMVar finishVar
        result `shouldBe` True