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 , IOE :> es
) )
databaseInit
:: (Database :> es, Error ServerError :> es) => Eff es ()
databaseInit = send DatabaseInit
databaseRead databaseRead
:: (ToField a, Show a, Database :> es, Error ServerError :> es) :: (ToField a, Show a, Database :> es, Error ServerError :> es)
=> (Query, a) -> Eff es [User] => (Query, a) -> Eff es [User]
@ -38,15 +42,17 @@ databaseWrite
databaseWrite = send . DatabaseWrite databaseWrite = send . DatabaseWrite
runDatabaseDebug :: DatabaseExeEffects es => Eff (Database : es) a -> Eff es a runDatabaseDebug :: DatabaseExeEffects es => Eff (Database : es) a -> Eff es a
runDatabaseDebug = interpret $ \ -> \case runDatabaseDebug = interpret $ \_ -> \case
DatabaseRead (statement, values) -> do DatabaseInit -> do
liftIOE $ putStrLn "Mocked setup of the database"
DatabaseRead (statement, values) -> do
liftIOE $ putStrLn liftIOE $ putStrLn
$ "Mocked a READ database operation with statement:\n" $ "Mocked a READ database operation with statement:\n"
++ show statement ++ show statement
++ " and values:\n" ++ " and values:\n"
++ show values ++ show values
pure [] pure []
DatabaseRead_ statement -> do DatabaseRead_ statement -> do
liftIOE $ putStrLn "Mocked a READ database operation on all users" liftIOE $ putStrLn "Mocked a READ database operation on all users"
pure [] pure []
DatabaseWrite (statement, values) -> do DatabaseWrite (statement, values) -> do
@ -55,28 +61,41 @@ runDatabaseDebug = interpret $ \ -> \case
runDatabaseIO :: DatabaseExeEffects es => Eff (Database : es) a -> Eff es a runDatabaseIO :: DatabaseExeEffects es => Eff (Database : es) a -> Eff es a
runDatabaseIO = interpret $ \_ -> \case runDatabaseIO = interpret $ \_ -> \case
DatabaseInit -> init
DatabaseRead (statement, values) -> read statement values DatabaseRead (statement, values) -> read statement values
DatabaseRead_ statement -> read_ statement DatabaseRead_ statement -> read_ statement
DatabaseWrite (statement, values) -> write statement values DatabaseWrite (statement, values) -> write statement values
where 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) read :: (ToField a, FromRow b, DatabaseExeEffects es)
=> Query -> a -> Eff es [b] => Query -> a -> Eff es [b]
read statement values = do read statement values = do
AppEnv { pool } <- ask AppEnv { pool } <- ask
liftIOE $ withResource pool $ \conn -> do liftWithPool pool $ \conn ->
query conn statement (Only values) query conn statement (Only values)
read_ :: (FromRow b, DatabaseExeEffects es) => Query -> Eff es [b] read_ :: (FromRow b, DatabaseExeEffects es) => Query -> Eff es [b]
read_ statement = do read_ statement = do
AppEnv { pool } <- ask AppEnv { pool } <- ask
liftIOE $ withResource pool $ \conn -> do liftWithPool pool $ \conn ->
query_ conn statement query_ conn statement
write :: (DatabaseExeEffects es, ToRow a) => Query -> a -> Eff es () write :: (DatabaseExeEffects es, ToRow a) => Query -> a -> Eff es ()
write statement values = do write statement values = do
AppEnv { pool } <- ask AppEnv { pool } <- ask
liftIOE $ withResource pool $ \conn -> do liftWithPool pool $ \conn -> do
execute conn statement values execute conn statement values
pure () pure ()
liftWithPool p f = liftIOE $ withResource p f
createConnectionPool :: IO (Pool Connection) createConnectionPool :: IO (Pool Connection)
createConnectionPool = newPool $ defaultPoolConfig createConnectionPool = newPool $ defaultPoolConfig
(connectPostgreSQL "host=localhost dbname=demo") (connectPostgreSQL "host=localhost dbname=demo")
@ -92,3 +111,19 @@ writeUser name = ("INSERT INTO users (name) VALUES (?);", Only name)
deleteUser :: UserId -> (Query, UserId) deleteUser :: UserId -> (Query, UserId)
deleteUser userId = ("DELETE FROM users WHERE id = ?;", 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 main = do
pool <- createConnectionPool pool <- createConnectionPool
let env = AppEnv { pool = pool } let env = AppEnv { pool = pool }
runEffStack env $ databaseInit
run port . serve proxy $ app env run port . serve proxy $ app env
app :: AppEnv -> Server AppAPI app :: AppEnv -> Server AppAPI
@ -36,7 +37,10 @@ transformEff :: AppEnv -> ServerT AppAPI AppEff -> ServerT AppAPI Handler
transformEff env = hoistServer proxy transformEff env = hoistServer proxy
$ Handler $ Handler
. ExceptT . ExceptT
. runEff . runEffStack env
runEffStack :: AppEnv -> AppEff a -> IO (Either ServerError a)
runEffStack env = runEff
. runErrorNoCallStack . runErrorNoCallStack
. runReader env . runReader env
. runDatabaseIO . runDatabaseIO