@@ -5,64 +5,40 @@ module App.Scotty
5
5
)
6
6
where
7
7
8
+ import App.AppEnv (AppEnv (appEnvConfig , appEnvHttpConfig ), appEnvInit )
8
9
import App.Cart
9
10
( BookingId ,
10
11
CartException (CartException ),
11
12
CartId (CartId ),
12
13
CartStatus (CartStatusLocked , CartStatusOpen , CartStatusPurchased ),
13
- HasCartConfig
14
- ( getBookingDelay ,
15
- getBookingUrl ,
16
- getPaymentDelay ,
17
- getPaymentUrl
18
- ),
19
14
PaymentId ,
20
15
getCartStatus ,
21
16
markCartAsPurchased ,
22
17
processBooking ,
23
18
processPayment ,
24
19
withCart ,
25
20
)
26
- import App.Config
27
- ( Config
28
- ( configBookingDelay ,
29
- configBookingUrl ,
30
- configDatabaseUrl ,
31
- configPaymentDelay ,
32
- configPaymentUrl ,
33
- configPurchaseDelay
34
- ),
35
- configInit ,
36
- )
37
- import App.Db (HasDbPool (getDbPool ), dbInit )
21
+ import App.Config (Config (configPurchaseDelay ))
38
22
import App.Json (defaultToJSON )
39
23
import Blammo.Logging
40
- ( HasLogger (loggerL ),
41
- Logger ,
42
- LoggingT ,
24
+ ( LoggingT ,
43
25
Message ((:#) ),
44
26
MonadLogger (monadLoggerLog ),
45
27
logInfo ,
46
28
logWarn ,
47
29
runLoggerLoggingT ,
48
30
(.=) ,
49
31
)
50
- import Blammo.Logging.Simple (newLoggerEnv )
51
32
import Control.Concurrent (threadDelay )
52
33
import Control.Monad.IO.Class (MonadIO (liftIO ))
53
34
import Control.Monad.Reader (MonadReader , ReaderT , asks , runReaderT )
54
35
import Control.Monad.Trans (lift )
55
36
import Data.Aeson (ToJSON (toJSON ), object )
56
- import Data.Pool (Pool )
57
37
import Data.String.Conversions (cs )
58
38
import Data.Text (Text )
59
- import Database.PostgreSQL.Simple (Connection )
60
39
import GHC.Generics (Generic )
61
- import Lens.Micro (lens )
62
40
import Network.HTTP.Req
63
- ( HttpConfig ,
64
- MonadHttp (getHttpConfig , handleHttpException ),
65
- defaultHttpConfig ,
41
+ ( MonadHttp (getHttpConfig , handleHttpException ),
66
42
)
67
43
import Network.HTTP.Types (Status , status404 , status409 , status500 )
68
44
import UnliftIO (MonadUnliftIO , throwIO )
@@ -82,60 +58,27 @@ import Web.Scotty.Trans
82
58
status ,
83
59
)
84
60
85
- data App = App
86
- { appConfig :: Config ,
87
- appLogger :: Logger ,
88
- appHttpConfig :: HttpConfig ,
89
- appDbPool :: Pool Connection
90
- }
91
-
92
- instance HasLogger App where
93
- loggerL = lens appLogger $ \ x y -> x {appLogger = y}
94
-
95
- instance HasCartConfig App where
96
- getBookingUrl = configBookingUrl . appConfig
97
- getBookingDelay = configBookingDelay . appConfig
98
- getPaymentUrl = configPaymentUrl . appConfig
99
- getPaymentDelay = configPaymentDelay . appConfig
100
-
101
- instance HasDbPool App where
102
- getDbPool = appDbPool
103
-
104
- appInit :: IO App
105
- appInit = do
106
- config <- configInit
107
- logger <- newLoggerEnv
108
- dbPool <- dbInit $ configDatabaseUrl config
109
- let app =
110
- App
111
- { appConfig = config,
112
- appLogger = logger,
113
- appHttpConfig = defaultHttpConfig,
114
- appDbPool = dbPool
115
- }
116
- pure app
117
-
118
- newtype AppM a = AppM
119
- { unAppM :: ReaderT App (LoggingT IO ) a
61
+ newtype App a = App
62
+ { unApp :: ReaderT AppEnv (LoggingT IO ) a
120
63
}
121
- deriving (Functor , Applicative , Monad , MonadIO , MonadReader App , MonadUnliftIO )
64
+ deriving (Functor , Applicative , Monad , MonadIO , MonadReader AppEnv , MonadUnliftIO )
122
65
123
- instance MonadLogger AppM where
66
+ instance MonadLogger App where
124
67
monadLoggerLog loc logSource logLevel msg =
125
- AppM $ lift $ monadLoggerLog loc logSource logLevel msg
68
+ App $ lift $ monadLoggerLog loc logSource logLevel msg
126
69
127
70
instance (ScottyError e , MonadLogger m ) => MonadLogger (ActionT e m ) where
128
71
monadLoggerLog loc logSource logLevel msg =
129
72
lift $ monadLoggerLog loc logSource logLevel msg
130
73
131
- instance MonadHttp AppM where
74
+ instance MonadHttp App where
132
75
handleHttpException = throwIO
133
- getHttpConfig = asks appHttpConfig
76
+ getHttpConfig = asks appEnvHttpConfig
134
77
135
- runApp :: AppM a -> IO a
78
+ runApp :: App a -> IO a
136
79
runApp m = do
137
- app <- appInit
138
- runLoggerLoggingT app $ runReaderT (unAppM m) app
80
+ app <- appEnvInit
81
+ runLoggerLoggingT app $ runReaderT (unApp m) app
139
82
140
83
data CartPurchaseResponse = CartPurchaseResponse
141
84
{ cartPurchaseResponseCartId :: CartId ,
@@ -148,7 +91,7 @@ data CartPurchaseResponse = CartPurchaseResponse
148
91
instance ToJSON CartPurchaseResponse where
149
92
toJSON = defaultToJSON " cartPurchaseResponse"
150
93
151
- postCartPurchaseHandler :: ActionT AppError AppM ()
94
+ postCartPurchaseHandler :: ActionT AppError App ()
152
95
postCartPurchaseHandler = do
153
96
cartId <- CartId <$> param " cartId"
154
97
cartStatusMaybe <- lift $ getCartStatus cartId
@@ -164,10 +107,10 @@ postCartPurchaseHandler = do
164
107
raiseAppError status409 " Cart locked"
165
108
Just CartStatusOpen -> do
166
109
logInfo $ " Cart purchase starting" :# [" cart_id" .= cartId]
167
- let purchase :: AppM CartPurchaseResponse
110
+ let purchase :: App CartPurchaseResponse
168
111
purchase = do
169
112
(bookingId, paymentId) <- concurrently (processBooking cartId) (processPayment cartId)
170
- purchaseDelay <- asks (configPurchaseDelay . appConfig )
113
+ purchaseDelay <- asks (configPurchaseDelay . appEnvConfig )
171
114
liftIO $ threadDelay purchaseDelay
172
115
markCartAsPurchased cartId
173
116
pure $
@@ -178,10 +121,10 @@ postCartPurchaseHandler = do
178
121
cartPurchaseResponsePaymentId = paymentId
179
122
}
180
123
181
- action :: AppM (Either Text CartPurchaseResponse )
124
+ action :: App (Either Text CartPurchaseResponse )
182
125
action = Right <$> withCart cartId purchase
183
126
184
- handleError :: CartException -> AppM (Either Text CartPurchaseResponse )
127
+ handleError :: CartException -> App (Either Text CartPurchaseResponse )
185
128
handleError (CartException msg) = pure $ Left msg
186
129
187
130
result <- lift $ catch action handleError
@@ -222,7 +165,7 @@ handleNotFound = do
222
165
msg = " Path not found"
223
166
json $ object [" error" .= msg]
224
167
225
- application :: ScottyT AppError AppM ()
168
+ application :: ScottyT AppError App ()
226
169
application = do
227
170
defaultHandler handleException
228
171
post " /cart/:cartId/purchase" postCartPurchaseHandler
0 commit comments