Cleanup type signatures and start working on debug env run
This commit is contained in:
parent
0808fe130a
commit
ffec891f26
21
src/Core.hs
21
src/Core.hs
@ -32,22 +32,23 @@ data AppEnv = AppEnv { pool :: Pool Connection }
|
||||
newtype UserId = UserId Int
|
||||
deriving (Show, Generic, FromField, ToField, FromHttpApiData, ToHttpApiData)
|
||||
|
||||
instance ToJSON UserId
|
||||
instance FromJSON UserId
|
||||
instance ToRow UserId
|
||||
instance FromRow UserId
|
||||
|
||||
data User = User { userId :: UserId, userName :: T.Text}
|
||||
deriving (Show, Generic)
|
||||
|
||||
instance FromRow User where
|
||||
fromRow = User <$> field <*> field
|
||||
instance ToRow User where
|
||||
toRow (User uid name) = toRow (uid, name)
|
||||
instance ToJSON UserId
|
||||
instance FromJSON UserId
|
||||
|
||||
instance ToRow UserId
|
||||
instance FromRow UserId
|
||||
|
||||
instance ToJSON User
|
||||
instance FromJSON User
|
||||
|
||||
instance ToRow User where
|
||||
toRow (User uid name) = toRow (uid, name)
|
||||
instance FromRow User where
|
||||
fromRow = User <$> field <*> field
|
||||
|
||||
data Database :: Effect where
|
||||
DatabaseInit
|
||||
:: Database (Eff es) ()
|
||||
@ -58,7 +59,7 @@ data Database :: Effect where
|
||||
DatabaseWrite
|
||||
:: (ToRow a, Show a) => (Query, a) -> Database (Eff es) ()
|
||||
|
||||
data Logger :: Effect where
|
||||
data Logger :: Effect where
|
||||
WriteLog :: LogLevel -> String -> Logger (Eff es) ()
|
||||
|
||||
data LogLevel = Info | Warning | Error
|
||||
|
@ -23,25 +23,54 @@ type DatabaseExeEffects es = ( Reader AppEnv :> es
|
||||
, IOE :> es
|
||||
)
|
||||
|
||||
databaseInit
|
||||
:: (Database :> es, Error ServerError :> es) => Eff 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]
|
||||
databaseRead :: (ToField a, Show a, Database :> es, Error ServerError :> es)
|
||||
=> (Query, a) -> Eff es [User]
|
||||
databaseRead = send . DatabaseRead
|
||||
|
||||
databaseRead_
|
||||
:: (Database :> es, Error ServerError :> es) => Query -> Eff es [User]
|
||||
databaseRead_ :: (Database :> es, Error ServerError :> es)
|
||||
=> Query -> Eff es [User]
|
||||
databaseRead_ = send . DatabaseRead_
|
||||
|
||||
databaseWrite
|
||||
:: (ToRow a, Show a, Database :> es, Error ServerError :> es)
|
||||
=> (Query, a) -> Eff es ()
|
||||
databaseWrite :: (ToRow a, Show a, Database :> es, Error ServerError :> es)
|
||||
=> (Query, a) -> Eff es ()
|
||||
databaseWrite = send . DatabaseWrite
|
||||
|
||||
runDatabaseDebug :: DatabaseExeEffects es => Eff (Database : es) a -> Eff es a
|
||||
runDatabaseIO :: DatabaseExeEffects es
|
||||
=> Eff (Database : es) a -> Eff es a
|
||||
runDatabaseIO = interpret $ \_ -> \case
|
||||
DatabaseInit -> do
|
||||
AppEnv { pool } <- ask
|
||||
liftWithPool pool $ \conn -> do
|
||||
execute_ conn createUsersTable
|
||||
execute_ conn createLogsTable
|
||||
pure ()
|
||||
|
||||
DatabaseRead (statement, values) -> do
|
||||
AppEnv { pool } <- ask
|
||||
liftWithPool pool $ \conn ->
|
||||
query conn statement (Only values)
|
||||
|
||||
DatabaseRead_ statement -> do
|
||||
AppEnv { pool } <- ask
|
||||
liftWithPool pool $ \conn ->
|
||||
query_ conn statement
|
||||
|
||||
DatabaseWrite (statement, values) -> do
|
||||
AppEnv { pool } <- ask
|
||||
liftWithPool pool $ \conn -> do
|
||||
execute conn statement values
|
||||
pure ()
|
||||
where
|
||||
liftWithPool :: (IOE :> es, Error ServerError :> es)
|
||||
=> (Pool Connection) -> (Connection -> IO a) -> Eff es a
|
||||
liftWithPool p f = liftIOE $ withResource p f
|
||||
|
||||
runDatabaseDebug :: DatabaseExeEffects es
|
||||
=> Eff (Database : es) a -> Eff es a
|
||||
runDatabaseDebug = interpret $ \_ -> \case
|
||||
DatabaseInit -> do
|
||||
liftIOE $ putStrLn "Mocked setup of the database"
|
||||
@ -49,7 +78,7 @@ runDatabaseDebug = interpret $ \_ -> \case
|
||||
liftIOE $ putStrLn
|
||||
$ "Mocked a READ database operation with statement:\n"
|
||||
++ show statement
|
||||
++ " and values:\n"
|
||||
++ "\nValues:\n"
|
||||
++ show values
|
||||
pure []
|
||||
DatabaseRead_ statement -> do
|
||||
@ -57,44 +86,10 @@ runDatabaseDebug = interpret $ \_ -> \case
|
||||
pure []
|
||||
DatabaseWrite (statement, values) -> do
|
||||
liftIOE $ putStrLn
|
||||
$ "Mocked a WRITE database operation with a user named " ++ show values
|
||||
|
||||
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 createUsersTable
|
||||
execute_ conn createLogsTable
|
||||
pure ()
|
||||
|
||||
read :: (ToField a, FromRow b, DatabaseExeEffects es)
|
||||
=> Query -> a -> Eff es [b]
|
||||
read statement values = do
|
||||
AppEnv { pool } <- ask
|
||||
liftWithPool pool $ \conn ->
|
||||
query conn statement (Only values)
|
||||
|
||||
read_ :: (FromRow b, DatabaseExeEffects es) => Query -> Eff es [b]
|
||||
read_ statement = do
|
||||
AppEnv { pool } <- ask
|
||||
liftWithPool pool $ \conn ->
|
||||
query_ conn statement
|
||||
|
||||
write :: (DatabaseExeEffects es, ToRow a) => Query -> a -> Eff es ()
|
||||
write statement values = do
|
||||
AppEnv { pool } <- ask
|
||||
liftWithPool pool $ \conn -> do
|
||||
execute conn statement values
|
||||
pure ()
|
||||
|
||||
liftWithPool p f = liftIOE $ withResource p f
|
||||
$ "Mocked a WRITE database operation with statement:\n"
|
||||
++ show statement
|
||||
++ "\nValues:\n"
|
||||
++ show values
|
||||
|
||||
createConnectionPool :: IO (Pool Connection)
|
||||
createConnectionPool = newPool $ defaultPoolConfig
|
||||
|
@ -14,24 +14,29 @@ import qualified Servant as S
|
||||
|
||||
type CRUD es = ( Database :> es, Logger :> es, Error ServerError :> es )
|
||||
|
||||
rootHandler :: (Logger :> es, Error ServerError :> es) => Eff es T.Text
|
||||
rootHandler :: (Logger :> es, Error ServerError :> es)
|
||||
=> Eff es T.Text
|
||||
rootHandler = (writeLog Info "Hit the root!") >>= \_ ->
|
||||
return "Hello, World!"
|
||||
|
||||
userListHandler :: CRUD es => Eff es [User]
|
||||
userListHandler :: CRUD es
|
||||
=> Eff es [User]
|
||||
userListHandler = (writeLog Info "Selected all users!") >>= \_ ->
|
||||
databaseRead_ "SELECT id, name FROM users"
|
||||
|
||||
userGetHandler :: CRUD es => UserId -> Eff es User
|
||||
userGetHandler :: CRUD es
|
||||
=> UserId -> Eff es User
|
||||
userGetHandler userId = databaseRead (queryUser userId) >>= \mUser ->
|
||||
case mUser of
|
||||
(a:_) -> pure a
|
||||
[] -> pure (User (UserId 0) "No user found")
|
||||
|
||||
userPostHandler :: CRUD es => T.Text -> Eff es NoContent
|
||||
userPostHandler :: CRUD es
|
||||
=> T.Text -> Eff es NoContent
|
||||
userPostHandler name =
|
||||
databaseWrite (writeUser name) >>= \_ -> return NoContent
|
||||
|
||||
userDeleteHandler :: CRUD es => UserId -> Eff es NoContent
|
||||
userDeleteHandler :: CRUD es
|
||||
=> UserId -> Eff es NoContent
|
||||
userDeleteHandler userId =
|
||||
databaseWrite (deleteUser userId) >>= \_ -> return NoContent
|
||||
|
@ -19,8 +19,8 @@ writeLog :: (Logger :> es, Error ServerError :> es)
|
||||
=> LogLevel -> String -> Eff es ()
|
||||
writeLog level msg = send (WriteLog level msg)
|
||||
|
||||
runLoggerConsole :: (Error ServerError :> es, IOE :> es) =>
|
||||
Eff (Logger : es) a -> Eff es a
|
||||
runLoggerConsole :: (Error ServerError :> es, IOE :> es)
|
||||
=> Eff (Logger : es) a -> Eff es a
|
||||
runLoggerConsole = interpret $ \_ -> \case
|
||||
WriteLog level msg -> do
|
||||
time <- liftIOE getCurrentTime
|
||||
@ -29,19 +29,9 @@ runLoggerConsole = interpret $ \_ -> \case
|
||||
++ "LEVEL: " ++ show level ++ "\n"
|
||||
++ "MESSAGE: " ++ msg
|
||||
|
||||
runLoggerPSQL :: LogToDatabase es => Eff (Logger : es) a -> Eff es a
|
||||
runLoggerPSQL :: LogToDatabase es
|
||||
=> Eff (Logger : es) a -> Eff es a
|
||||
runLoggerPSQL = interpret $ \_ -> \case
|
||||
WriteLog level msg ->
|
||||
databaseWrite
|
||||
("INSERT INTO logs (level, message) VALUES (?,?);", (level, msg))
|
||||
|
||||
{-
|
||||
CREATE TABLE 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
|
||||
);
|
||||
-}
|
||||
|
@ -42,6 +42,13 @@ runAppEff env = runEff
|
||||
. runDatabaseIO
|
||||
. runLoggerPSQL
|
||||
|
||||
runAppDebug :: AppEnv -> AppEff a -> IO (Either ServerError a)
|
||||
runAppDebug env = runEff
|
||||
. runErrorNoCallStack
|
||||
. runReader env
|
||||
. runDatabaseDebug
|
||||
. runLoggerConsole
|
||||
|
||||
port :: Int
|
||||
port = 8080
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user