packages feed

hasql-pool 1.4.1 → 1.4.2

raw patch · 5 files changed

+87/−15 lines, 5 files

Files

hasql-pool.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: hasql-pool-version: 1.4.1+version: 1.4.2 category: Hasql, Database, PostgreSQL synopsis: Pool of connections for Hasql homepage: https://github.com/nikita-volkov/hasql-pool
src/integration-tests/Specs/BySubject/UseSpec.hs view
@@ -1,6 +1,11 @@ module Specs.BySubject.UseSpec where +import Data.Text qualified as Text+import Hasql.Decoders qualified as Decoders+import Hasql.Encoders qualified as Encoders import Hasql.Pool+import Hasql.Session qualified as Session+import Hasql.Statement qualified as Statement import Helpers.Scripts qualified as Scripts import Helpers.Sessions qualified as Sessions import Test.Hspec@@ -38,3 +43,41 @@       _ <- use pool $ Sessions.badQuery       res <- use pool $ Sessions.selectOne       shouldSatisfy res $ isRight++  it "Cached type errors cause eviction of connection" \scopeParams -> do+    typeName <- Text.replace "-" "_" <$> Scripts.generateName "cached_type_"+    Scripts.onAutotaggedPool 1 10 1_800 1_800 scopeParams \_ pool -> do+      use pool (Session.script (createTypeSql typeName)) `shouldReturn` Right ()+      use pool (roundtripEnum typeName "ok") `shouldReturn` Right "ok"+      use pool (Session.script (recreateTypeSql typeName)) `shouldReturn` Right ()+      res <- use pool (roundtripEnum typeName "ok")+      shouldSatisfy res \case+        Left (SessionUsageError _) -> True+        _ -> False+      use pool (roundtripEnum typeName "ok") `shouldReturn` Right "ok"++quoteIdentifier :: Text -> Text+quoteIdentifier identifier =+  "\"" <> Text.replace "\"" "\"\"" identifier <> "\""++createTypeSql :: Text -> Text+createTypeSql typeName =+  "create type " <> quotedTypeName <> " as enum ('sad', 'ok', 'happy')"+  where+    quotedTypeName = quoteIdentifier typeName++recreateTypeSql :: Text -> Text+recreateTypeSql typeName =+  "drop type " <> quotedTypeName <> "; create type " <> quotedTypeName <> " as enum ('sad', 'ok', 'happy')"+  where+    quotedTypeName = quoteIdentifier typeName++roundtripEnum :: Text -> Text -> Session.Session Text+roundtripEnum typeName value =+  Session.statement value statement+  where+    statement =+      Statement.preparable+        ("select $1 :: " <> quoteIdentifier typeName)+        (Encoders.param (Encoders.nonNullable (Encoders.enum Nothing typeName id)))+        (Decoders.singleRow (Decoders.column (Decoders.nonNullable (Decoders.enum Nothing typeName Just))))
src/library/exposed/Hasql/Pool.hs view
@@ -217,19 +217,20 @@           returnConn           throwIO exc         Right (Left err) ->-          ErrorsDestruction.reset-            ( \details -> do-                Connection.release (entryConnection entry)-                atomically $ modifyTVar' poolCapacity succ-                poolObserver (ConnectionObservation (entryId entry) (TerminatedConnectionStatus (NetworkErrorConnectionTerminationReason (Just details))))-                return $ Left $ SessionUsageError err-            )-            ( do-                returnConn-                poolObserver (ConnectionObservation (entryId entry) (ReadyForUseConnectionStatus (SessionFailedConnectionReadyForUseReason err)))-                return $ Left $ SessionUsageError err-            )-            err+          if ErrorsDestruction.requiresConnectionDiscard err+            then do+              Connection.release (entryConnection entry)+              atomically $ modifyTVar' poolCapacity succ+              poolObserver+                ( ConnectionObservation+                    (entryId entry)+                    (TerminatedConnectionStatus (NetworkErrorConnectionTerminationReason (ErrorsDestruction.discardDetails err)))+                )+              return $ Left $ SessionUsageError err+            else do+              returnConn+              poolObserver (ConnectionObservation (entryId entry) (ReadyForUseConnectionStatus (SessionFailedConnectionReadyForUseReason err)))+              return $ Left $ SessionUsageError err         Right (Right res) -> do           returnConn           poolObserver (ConnectionObservation (entryId entry) (ReadyForUseConnectionStatus SessionSucceededConnectionReadyForUseReason))
src/library/exposed/Hasql/Pool/Observation.hs view
@@ -51,7 +51,11 @@     AgingConnectionTerminationReason   | -- | The timeout of how long a connection may remain idle in the pool has passed.     IdlenessConnectionTerminationReason-  | -- | Connectivity issues with the server.+  | -- | The connection became unusable and had to be discarded.+    --+    -- This includes connectivity issues with the server as well as fatal+    -- session errors that invalidate the connection's prepared statement or+    -- type caches.     NetworkErrorConnectionTerminationReason (Maybe Text)   | -- | User has invoked the 'Hasql.Pool.release' procedure.     ReleaseConnectionTerminationReason
src/library/other/Hasql/Pool/SessionErrorDestructors.hs view
@@ -7,3 +7,27 @@ reset onReset onNoReset = \case   Errors.ConnectionSessionError details -> onReset details   _ -> onNoReset++requiresConnectionDiscard :: Errors.SessionError -> Bool+requiresConnectionDiscard = \case+  Errors.ConnectionSessionError {} -> True+  Errors.MissingTypesSessionError {} -> True+  Errors.ScriptSessionError _ serverError -> isStaleServerError serverError+  Errors.StatementSessionError _ _ _ _ _ statementError -> statementRequiresConnectionDiscard statementError+  Errors.DriverSessionError {} -> False++discardDetails :: Errors.SessionError -> Maybe Text+discardDetails err =+  if requiresConnectionDiscard err+    then Just $ Errors.toMessage err+    else Nothing++statementRequiresConnectionDiscard :: Errors.StatementError -> Bool+statementRequiresConnectionDiscard = \case+  Errors.ServerStatementError serverError -> isStaleServerError serverError+  Errors.UnexpectedColumnTypeStatementError {} -> True+  _ -> False++isStaleServerError :: Errors.ServerError -> Bool+isStaleServerError (Errors.ServerError code _ _ _ _) =+  code == "0A000" || code == "XX000"