Skip to content

Commit acd289d

Browse files
authored
Merge pull request #20 from MatrixAI/service
Warp and Logging and Application Transformer Demo
2 parents b2c5660 + b10156f commit acd289d

File tree

5 files changed

+146
-6
lines changed

5 files changed

+146
-6
lines changed
File renamed without changes.

app/service/Main.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module Main where
2+
3+
import Demo as Demo
4+
5+
main :: IO ()
6+
main = Demo.runDemoApp

default.nix

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
1-
{ mkDerivation, base, hpack, stdenv }:
1+
{ mkDerivation, base, data-default-class, hpack, http-types
2+
, iproute, monad-logger, mtl, network, safe-exceptions, stdenv
3+
, transformers, wai, warp
4+
}:
25
mkDerivation {
36
pname = "haskell-demo";
47
version = "0.1.0.0";
58
src = ./.;
69
isLibrary = true;
710
isExecutable = true;
8-
libraryHaskellDepends = [ base ];
11+
libraryHaskellDepends = [
12+
base data-default-class http-types iproute monad-logger mtl network
13+
safe-exceptions transformers wai warp
14+
];
915
libraryToolDepends = [ hpack ];
10-
executableHaskellDepends = [ base ];
11-
testHaskellDepends = [ base ];
16+
executableHaskellDepends = [
17+
base data-default-class http-types iproute monad-logger mtl network
18+
safe-exceptions transformers wai warp
19+
];
20+
testHaskellDepends = [
21+
base data-default-class http-types iproute monad-logger mtl network
22+
safe-exceptions transformers wai warp
23+
];
1224
prePatch = "hpack";
1325
homepage = "https://github.com/MatrixAI/Haskell-Demo#readme";
1426
license = stdenv.lib.licenses.asl20;

package.yaml

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@ description: Please see the README on Github at <https://github.com/Matr
1414

1515
dependencies:
1616
- base >= 4.7 && < 5
17+
- transformers
18+
- mtl
19+
- monad-logger
20+
- safe-exceptions
21+
- network
22+
- iproute
23+
- wai
24+
- warp
25+
- http-types
26+
- data-default-class
1727

1828
library:
1929
source-dirs: src
@@ -28,11 +38,21 @@ library:
2838
exposed-modules:
2939
- Lib
3040
- FFI
41+
- Demo
3142

3243
executables:
33-
haskell-demo-exe:
44+
haskell-demo-ffi-exe:
3445
main: Main.hs
35-
source-dirs: app
46+
source-dirs: app/ffi
47+
ghc-options:
48+
- -threaded
49+
- -rtsopts
50+
- -with-rtsopts=-N
51+
dependencies:
52+
- haskell-demo
53+
haskell-demo-service-exe:
54+
main: Main.hs
55+
source-dirs: app/service
3656
ghc-options:
3757
- -threaded
3858
- -rtsopts

src/Demo.hs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2+
{-# LANGUAGE OverloadedStrings #-}
3+
{-# LANGUAGE TemplateHaskell #-}
4+
5+
module Demo where
6+
7+
import Control.Exception.Safe as E
8+
import Control.Exception.Safe ( MonadCatch
9+
, MonadMask
10+
, MonadThrow
11+
)
12+
import Control.Monad.IO.Class ( MonadIO
13+
, liftIO
14+
)
15+
import Control.Monad.Logger as L
16+
import Control.Monad.Logger ( LoggingT
17+
, MonadLogger
18+
)
19+
import Control.Monad.Reader ( MonadReader
20+
, ReaderT
21+
, ask
22+
, runReaderT
23+
)
24+
import Control.Monad.Trans.Class ( MonadTrans
25+
, lift
26+
)
27+
import Data.Default.Class ( Default
28+
, def
29+
)
30+
import Data.IP ( IP )
31+
import Data.String ( fromString )
32+
import Network.HTTP.Types as HTTP
33+
import Network.HTTP.Types.Header as HTTPHeaders
34+
import Network.Socket ( PortNumber )
35+
import Network.Wai ( Application )
36+
import Network.Wai as Wai
37+
import Network.Wai.Handler.Warp as Warp
38+
import System.Environment ( lookupEnv )
39+
40+
41+
data DemoEnv = DemoEnv { demoEnvHost :: IP,
42+
demoEnvPort :: PortNumber
43+
} deriving (Show)
44+
45+
-- this is the default demoenv
46+
instance Default DemoEnv where
47+
def = DemoEnv "127.0.0.1" 55555
48+
49+
newtype DemoT m a = DemoT
50+
{ runDemoT :: ReaderT DemoEnv (LoggingT m) a }
51+
deriving (
52+
Functor,
53+
Applicative,
54+
Monad,
55+
MonadIO,
56+
MonadThrow,
57+
MonadCatch,
58+
MonadLogger,
59+
MonadReader DemoEnv
60+
)
61+
62+
type Demo = DemoT IO
63+
64+
runDemo :: DemoEnv -> Demo a -> IO a
65+
runDemo env demo = do
66+
runStderrLoggingT $ runReaderT (runDemoT demo) env
67+
68+
warpApp :: Application
69+
warpApp req respond = E.bracket_
70+
(runStderrLoggingT ($(L.logInfo) "Try IO Block"))
71+
(runStderrLoggingT ($(L.logInfo) "Clean IO Block"))
72+
(respond $ Wai.responseLBS HTTP.status200
73+
[(HTTPHeaders.hContentType, "text/plain")]
74+
"Hello from Demo!\n"
75+
)
76+
77+
demoApp :: Demo ()
78+
demoApp = do
79+
$(L.logInfo) "Starting Demo Server"
80+
DemoEnv ip port <- ask
81+
let settings =
82+
Warp.setHost (fromString $ show ip)
83+
$ Warp.setPort (fromIntegral port)
84+
$ Warp.defaultSettings
85+
$(L.logInfo) $ fromString $ "Running on " ++ show ip ++ ":" ++ show port
86+
liftIO $ Warp.runSettings settings warpApp
87+
$(L.logInfo) "Terminated Demo Server"
88+
89+
runDemoApp :: IO ()
90+
runDemoApp = do
91+
demoHost <- lookupEnv "DEMO_HOST"
92+
demoPort <- lookupEnv "DEMO_PORT"
93+
let defaultEnv = def :: DemoEnv
94+
defaultEnv <- return $ maybe
95+
defaultEnv
96+
(\host -> defaultEnv { demoEnvHost = read host })
97+
demoHost
98+
defaultEnv <- return $ maybe
99+
defaultEnv
100+
(\port -> defaultEnv { demoEnvPort = read port })
101+
demoPort
102+
runDemo defaultEnv demoApp

0 commit comments

Comments
 (0)