{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Network.Wait.PostgreSQL (
PostgreSqlConnectInfo(..),
waitPostgreSql,
waitPostgreSqlVerbose,
waitPostgreSqlVerboseFormat,
waitPostgreSqlWith
) where
import Data.ByteString ( ByteString )
import Control.Monad
import Control.Monad.Catch
import Control.Monad.IO.Class
import Control.Retry
import Database.PostgreSQL.Simple
import Database.PostgreSQL.Simple.Internal
import Network.Wait
class PostgreSqlConnectInfo a where
connectDb :: a -> IO Connection
instance PostgreSqlConnectInfo ConnectInfo where
connectDb :: ConnectInfo -> IO Connection
connectDb = ConnectInfo -> IO Connection
connect
instance PostgreSqlConnectInfo ByteString where
connectDb :: ByteString -> IO Connection
connectDb = ByteString -> IO Connection
connectPostgreSQL
waitPostgreSql
:: (MonadIO m, MonadMask m, PostgreSqlConnectInfo info)
=> RetryPolicyM m -> info -> m Connection
waitPostgreSql :: forall (m :: * -> *) info.
(MonadIO m, MonadMask m, PostgreSqlConnectInfo info) =>
RetryPolicyM m -> info -> m Connection
waitPostgreSql = [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> info -> m Connection
forall (m :: * -> *) info.
(MonadIO m, MonadMask m, PostgreSqlConnectInfo info) =>
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> info -> m Connection
waitPostgreSqlWith []
waitPostgreSqlVerbose
:: (MonadIO m, MonadMask m, PostgreSqlConnectInfo info)
=> (String -> m ()) -> RetryPolicyM m -> info -> m Connection
waitPostgreSqlVerbose :: forall (m :: * -> *) info.
(MonadIO m, MonadMask m, PostgreSqlConnectInfo info) =>
(String -> m ()) -> RetryPolicyM m -> info -> m Connection
waitPostgreSqlVerbose String -> m ()
out =
forall e (m :: * -> *) info.
(MonadIO m, MonadMask m, PostgreSqlConnectInfo info,
Exception e) =>
(Bool -> e -> RetryStatus -> m ())
-> RetryPolicyM m -> info -> m Connection
waitPostgreSqlVerboseFormat @SomeException ((Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m -> info -> m Connection)
-> (Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m
-> info
-> m Connection
forall a b. (a -> b) -> a -> b
$
\Bool
b SomeException
ex RetryStatus
st -> String -> m ()
out (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ Bool -> SomeException -> RetryStatus -> String
forall e. Exception e => Bool -> e -> RetryStatus -> String
defaultLogMsg Bool
b SomeException
ex RetryStatus
st
waitPostgreSqlVerboseFormat
:: forall e m info. (MonadIO m, MonadMask m, PostgreSqlConnectInfo info, Exception e)
=> (Bool -> e -> RetryStatus -> m ())
-> RetryPolicyM m
-> info
-> m Connection
waitPostgreSqlVerboseFormat :: forall e (m :: * -> *) info.
(MonadIO m, MonadMask m, PostgreSqlConnectInfo info,
Exception e) =>
(Bool -> e -> RetryStatus -> m ())
-> RetryPolicyM m -> info -> m Connection
waitPostgreSqlVerboseFormat Bool -> e -> RetryStatus -> m ()
out = [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> info -> m Connection
forall (m :: * -> *) info.
(MonadIO m, MonadMask m, PostgreSqlConnectInfo info) =>
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> info -> m Connection
waitPostgreSqlWith [RetryStatus -> Handler m Bool
h]
where h :: RetryStatus -> Handler m Bool
h = (e -> m Bool)
-> (Bool -> e -> RetryStatus -> m ())
-> RetryStatus
-> Handler m Bool
forall (m :: * -> *) e.
(Monad m, Exception e) =>
(e -> m Bool)
-> (Bool -> e -> RetryStatus -> m ())
-> RetryStatus
-> Handler m Bool
logRetries (m Bool -> e -> m Bool
forall a b. a -> b -> a
const (m Bool -> e -> m Bool) -> m Bool -> e -> m Bool
forall a b. (a -> b) -> a -> b
$ Bool -> m Bool
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True) Bool -> e -> RetryStatus -> m ()
out
waitPostgreSqlWith
:: (MonadIO m, MonadMask m, PostgreSqlConnectInfo info)
=> [RetryStatus -> Handler m Bool] -> RetryPolicyM m -> info
-> m Connection
waitPostgreSqlWith :: forall (m :: * -> *) info.
(MonadIO m, MonadMask m, PostgreSqlConnectInfo info) =>
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> info -> m Connection
waitPostgreSqlWith [RetryStatus -> Handler m Bool]
hs RetryPolicyM m
policy info
info =
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> m Connection -> m Connection
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
[RetryStatus -> Handler m Bool] -> RetryPolicyM m -> m a -> m a
recoveringWith [RetryStatus -> Handler m Bool]
hs RetryPolicyM m
policy (m Connection -> m Connection) -> m Connection -> m Connection
forall a b. (a -> b) -> a -> b
$
IO Connection -> m Connection
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Connection -> m Connection) -> IO Connection -> m Connection
forall a b. (a -> b) -> a -> b
$
IO Connection
-> (Connection -> IO ())
-> (Connection -> IO Connection)
-> IO Connection
forall (m :: * -> *) a c b.
(HasCallStack, MonadMask m) =>
m a -> (a -> m c) -> (a -> m b) -> m b
bracket (info -> IO Connection
forall a. PostgreSqlConnectInfo a => a -> IO Connection
connectDb info
info) Connection -> IO ()
close ((Connection -> IO Connection) -> IO Connection)
-> (Connection -> IO Connection) -> IO Connection
forall a b. (a -> b) -> a -> b
$ \Connection
con -> do
rs <- forall r. FromRow r => Connection -> Query -> IO [r]
query_ @[Int] Connection
con Query
"SELECT 1;"
unless (rs == [[1]]) $ throwM $
fatalError "Unexpected result for SELECT 1."
pure con