Add Database init effect and integrate with main entrypoint

This commit is contained in:
James Eversole 2024-10-14 11:27:50 -05:00
parent f38e5bc5f5
commit a7836ad08f
2 changed files with 46 additions and 7 deletions

View File

@ -23,6 +23,10 @@ type DatabaseExeEffects es = ( Reader AppEnv :> es
, IOE :> es
)
databaseInit
:: (Database :> es, Error ServerError :> es) => Eff es ()
databaseInit = send DatabaseInit
databaseRead
:: (ToField a, Show a, Database :> es, Error ServerError :> es)
=> (Query, a) -> Eff es [User]
@ -38,15 +42,17 @@ databaseWrite
databaseWrite = send . DatabaseWrite
runDatabaseDebug :: DatabaseExeEffects es => Eff (Database : es) a -> Eff es a
runDatabaseDebug = interpret $ \ -> \case
DatabaseRead (statement, values) -> do
runDatabaseDebug = interpret $ \_ -> \case
DatabaseInit -> do
liftIOE $ putStrLn "Mocked setup of the database"
DatabaseRead (statement, values) -> do
liftIOE $ putStrLn
$ "Mocked a READ database operation with statement:\n"
++ show statement
++ " and values:\n"
++ show values
pure []
DatabaseRead_ statement -> do
DatabaseRead_ statement -> do
liftIOE $ putStrLn "Mocked a READ database operation on all users"
pure []
DatabaseWrite (statement, values) -> do
@ -55,28 +61,41 @@ runDatabaseDebug = interpret $ \ -> \case
runDatabaseIO :: DatabaseExeEffects es => Eff (Database : es) a -> Eff es a
runDatabaseIO = interpret $ \_ -> \case
DatabaseInit -> init
DatabaseRead (statement, values) -> read statement values
DatabaseRead_ statement -> read_ statement
DatabaseWrite (statement, values) -> write statement values
where
init :: DatabaseExeEffects es => Eff es ()
init = do
AppEnv { pool } <- ask
liftWithPool pool $ \conn -> do
execute_ conn tableUsers
execute_ conn tableLogs
pure ()
read :: (ToField a, FromRow b, DatabaseExeEffects es)
=> Query -> a -> Eff es [b]
read statement values = do
AppEnv { pool } <- ask
liftIOE $ withResource pool $ \conn -> do
liftWithPool pool $ \conn ->
query conn statement (Only values)
read_ :: (FromRow b, DatabaseExeEffects es) => Query -> Eff es [b]
read_ statement = do
AppEnv { pool } <- ask
liftIOE $ withResource pool $ \conn -> do
liftWithPool pool $ \conn ->
query_ conn statement
write :: (DatabaseExeEffects es, ToRow a) => Query -> a -> Eff es ()
write statement values = do
AppEnv { pool } <- ask
liftIOE $ withResource pool $ \conn -> do
liftWithPool pool $ \conn -> do
execute conn statement values
pure ()
liftWithPool p f = liftIOE $ withResource p f
createConnectionPool :: IO (Pool Connection)
createConnectionPool = newPool $ defaultPoolConfig
(connectPostgreSQL "host=localhost dbname=demo")
@ -92,3 +111,19 @@ writeUser name = ("INSERT INTO users (name) VALUES (?);", Only name)
deleteUser :: UserId -> (Query, UserId)
deleteUser userId = ("DELETE FROM users WHERE id = ?;", userId)
tableUsers :: Query
tableUsers = "CREATE TABLE IF NOT EXISTS users ( \
\id integer NOT NULL, \
\name character varying(255) NOT NULL \
\);"
tableLogs :: Query
tableLogs = "CREATE TABLE IF NOT EXISTS logs ( \
\ id SERIAL PRIMARY KEY, \
\ level VARCHAR(10) NOT NULL, \
\ message TEXT NOT NULL, \
\ timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(), \
\ source VARCHAR(100), \
\ context JSONB \
\);"

View File

@ -22,6 +22,7 @@ main :: IO ()
main = do
pool <- createConnectionPool
let env = AppEnv { pool = pool }
runEffStack env $ databaseInit
run port . serve proxy $ app env
app :: AppEnv -> Server AppAPI
@ -36,7 +37,10 @@ transformEff :: AppEnv -> ServerT AppAPI AppEff -> ServerT AppAPI Handler
transformEff env = hoistServer proxy
$ Handler
. ExceptT
. runEff
. runEffStack env
runEffStack :: AppEnv -> AppEff a -> IO (Either ServerError a)
runEffStack env = runEff
. runErrorNoCallStack
. runReader env
. runDatabaseIO