{-# LANGUAGE TypeApplications #-}
module Gargoyle.PostgreSQL.Connect (withDb, withDb', openDb) where
import Control.Monad ((>=>))
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as C8
import Data.Pool (Pool, defaultPoolConfig, newPool, setNumStripes)
import Database.PostgreSQL.Simple (Connection, close, connectPostgreSQL)
import Gargoyle (withGargoyle)
import Gargoyle.PostgreSQL.Nix (postgresNix)
import System.Directory (doesFileExist)
withDb :: String -> (Pool Connection -> IO a) -> IO a
withDb :: forall a. String -> (Pool Connection -> IO a) -> IO a
withDb String
dbPath Pool Connection -> IO a
f = (String -> IO a) -> (a -> IO a) -> Either String a -> IO a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> IO a
forall a. HasCallStack => String -> a
error a -> IO a
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String a -> IO a) -> IO (Either String a) -> IO a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< String -> (ByteString -> IO a) -> IO (Either String a)
forall a. String -> (ByteString -> IO a) -> IO (Either String a)
withDb' String
dbPath (ByteString -> IO (Pool Connection)
openDb (ByteString -> IO (Pool Connection))
-> (Pool Connection -> IO a) -> ByteString -> IO a
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Pool Connection -> IO a
f)
openDb :: ByteString -> IO (Pool Connection)
openDb :: ByteString -> IO (Pool Connection)
openDb ByteString
dbUri = PoolConfig Connection -> IO (Pool Connection)
forall a. PoolConfig a -> IO (Pool a)
newPool (PoolConfig Connection -> IO (Pool Connection))
-> PoolConfig Connection -> IO (Pool Connection)
forall a b. (a -> b) -> a -> b
$ Maybe Int -> PoolConfig Connection -> PoolConfig Connection
forall a. Maybe Int -> PoolConfig a -> PoolConfig a
setNumStripes (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1) (PoolConfig Connection -> PoolConfig Connection)
-> PoolConfig Connection -> PoolConfig Connection
forall a b. (a -> b) -> a -> b
$ IO Connection
-> (Connection -> IO ()) -> Double -> Int -> PoolConfig Connection
forall a. IO a -> (a -> IO ()) -> Double -> Int -> PoolConfig a
defaultPoolConfig (ByteString -> IO Connection
connectPostgreSQL ByteString
dbUri) Connection -> IO ()
close (forall a b. (Real a, Fractional b) => a -> b
realToFrac @Int Int
5) Int
20
withDb' :: String -> (ByteString -> IO a) -> IO (Either String a)
withDb' :: forall a. String -> (ByteString -> IO a) -> IO (Either String a)
withDb' String
dbPath ByteString -> IO a
f = do
dbExists <- String -> IO Bool
doesFileExist String
dbPath
if dbExists
then C8.readFile dbPath >>= \ByteString
b -> case ByteString -> [ByteString]
C8.lines ByteString
b of
[] -> Either String a -> IO (Either String a)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String a -> IO (Either String a))
-> Either String a -> IO (Either String a)
forall a b. (a -> b) -> a -> b
$ String -> Either String a
forall a b. a -> Either a b
Left String
"DB connection string configuration file is empty"
ByteString
x:[ByteString]
_ -> a -> Either String a
forall a b. b -> Either a b
Right (a -> Either String a) -> IO a -> IO (Either String a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteString -> IO a
f ByteString
x
else do
g <- postgresNix
Right <$> withGargoyle g dbPath f