Repository navigation
Expand file tree
/
Copy pathApplicationAssembly.hs
More file actions
54 lines (48 loc) · 2.43 KB
/
Copy pathApplicationAssembly.hs
File metadata and controls
54 lines (48 loc) · 2.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
module ExternalInterfaces.ApplicationAssembly where
import Control.Monad.Except
import Data.ByteString.Lazy.Char8 (pack)
import Data.Function ((&))
import InterfaceAdapters.Config
import InterfaceAdapters.KVSFileServer (runKvsAsFileServer)
import InterfaceAdapters.KVSSqlite (runKvsAsSQLite)
import InterfaceAdapters.ReservationRestService
import Polysemy
import Polysemy.Error
import Polysemy.Input (Input, runInputConst)
import Polysemy.Trace (Trace, traceToIO, ignoreTrace)
import Servant.Server
import UseCases.KVS
import UseCases.ReservationUseCase
import Data.Aeson.Types (ToJSON, FromJSON)
-- | creates the WAI Application that can be executed by Warp.run.
-- All Polysemy interpretations must be executed here.
createApp :: Config -> Application
createApp config = serve reservationAPI (liftServer config)
liftServer :: Config -> ServerT ReservationAPI Handler
liftServer config = hoistServer reservationAPI (interpretServer config) reservationServer
where
interpretServer conf sem = sem
& selectKvsBackend conf
& runInputConst conf
& runError @ReservationError
& selectTraceVerbosity conf
& runM
& liftToHandler
liftToHandler = Handler . ExceptT . fmap handleErrors
handleErrors (Left (ReservationNotPossible msg)) = Left err412 { errBody = pack msg}
handleErrors (Right value) = Right value
-- | can select between SQLite or FileServer persistence backends.
selectKvsBackend :: (Member (Input Config) r, Member (Embed IO) r, Member Trace r, Show k, Read k, ToJSON v, FromJSON v)
=> Config -> Sem (KVS k v : r) a -> Sem r a
selectKvsBackend config = case backend config of
SQLite -> runKvsAsSQLite
FileServer -> runKvsAsFileServer
-- | if the config flag verbose is set to True, trace to Console, else ignore all trace messages
selectTraceVerbosity :: (Member (Embed IO) r) => Config -> (Sem (Trace : r) a -> Sem r a)
selectTraceVerbosity config =
if verbose config
then traceToIO
else ignoreTrace
-- | load application config. In real life, this would load a config file or read commandline args.
loadConfig :: IO Config
loadConfig = return Config {port = 8080, backend = SQLite, dbPath = "kvs.db", verbose = True}