|
@@ -3,47 +3,22 @@
|
|
|
|
|
|
module Main where
|
|
module Main where
|
|
|
|
|
|
-import Control.Concurrent.Async (mapConcurrently)
|
|
|
|
|
|
+import Control.Concurrent.Async (mapConcurrently)
|
|
import Control.Monad.IO.Class
|
|
import Control.Monad.IO.Class
|
|
-import Data.Aeson hiding (json)
|
|
|
|
-import Data.Maybe (catMaybes, listToMaybe)
|
|
|
|
-import qualified Data.Text as T
|
|
|
|
-import qualified Database.PostgreSQL.Simple as PG
|
|
|
|
-import Database.PostgreSQL.Simple.FromRow
|
|
|
|
|
|
+import Data.Aeson hiding (json)
|
|
|
|
+import Data.List (sort)
|
|
|
|
+import Data.Maybe (catMaybes)
|
|
|
|
+import qualified Database.PostgreSQL.Simple as PG
|
|
import GHC.Exts
|
|
import GHC.Exts
|
|
import Network.HTTP.Types.Status
|
|
import Network.HTTP.Types.Status
|
|
import System.Random
|
|
import System.Random
|
|
|
|
+import Text.Blaze.Html.Renderer.Utf8
|
|
|
|
+import qualified Text.Blaze.Html5 as H
|
|
import Web.Spock.Safe
|
|
import Web.Spock.Safe
|
|
|
|
|
|
-
|
|
|
|
-data World = World
|
|
|
|
- { _idW :: Integer
|
|
|
|
- , _randomNumberW :: Integer
|
|
|
|
- } deriving (Show)
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-instance ToJSON World where
|
|
|
|
- toJSON w = object
|
|
|
|
- [ "id" .= _idW w
|
|
|
|
- , "randomNumber" .= _randomNumberW w
|
|
|
|
- ]
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-instance FromRow World where
|
|
|
|
- fromRow = World <$> field <*> field
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-fetchWorldById :: Int -> PG.Connection -> IO (Maybe World)
|
|
|
|
-fetchWorldById i c =
|
|
|
|
- listToMaybe <$> PG.query c
|
|
|
|
- "SELECT id, randomNumber FROM World WHERE id = (?)"
|
|
|
|
- (PG.Only i)
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-data Fortune = Fortune
|
|
|
|
- { _idF :: Integer
|
|
|
|
- , _messageF :: T.Text
|
|
|
|
- } deriving (Show)
|
|
|
|
|
|
+import Models.Fortune
|
|
|
|
+import Models.World
|
|
|
|
+import Views.Fortune
|
|
|
|
|
|
|
|
|
|
dbConn :: PoolOrConn PG.Connection
|
|
dbConn :: PoolOrConn PG.Connection
|
|
@@ -60,29 +35,42 @@ dbConn =
|
|
(PoolCfg 5 5 60))
|
|
(PoolCfg 5 5 60))
|
|
|
|
|
|
|
|
|
|
|
|
+blaze :: MonadIO m => H.Html -> ActionCtxT ctx m a
|
|
|
|
+blaze h = do
|
|
|
|
+ setHeader "Content-Type" "text/html"
|
|
|
|
+ lazyBytes $ renderHtml h
|
|
|
|
+{-# INLINE blaze #-}
|
|
|
|
+
|
|
|
|
+
|
|
main :: IO ()
|
|
main :: IO ()
|
|
main =
|
|
main =
|
|
- runSpock 3000 $ spock (defaultSpockCfg Nothing dbConn ()) $
|
|
|
|
- -- | Test 1: JSON serialization
|
|
|
|
- do get "json" $
|
|
|
|
- json $ Object (fromList [("message", "Hello, World!")])
|
|
|
|
- -- | Test 2: Single database query
|
|
|
|
- get "db" $
|
|
|
|
- do rand <- liftIO $ randomRIO (1, 10000)
|
|
|
|
- maybeWorld <- runQuery $ fetchWorldById rand
|
|
|
|
- case maybeWorld of
|
|
|
|
- Just w -> json w
|
|
|
|
- Nothing -> setStatus status404 >> text "World not found."
|
|
|
|
- -- | Test 3: Multiple database queries
|
|
|
|
- get "queries" $
|
|
|
|
- do queries <- max 1 . min 500 <$> param' "queries"
|
|
|
|
- let runSQL core = runSpockIO core . runQuery . fetchWorldById =<< randomRIO (1, 10000)
|
|
|
|
- spockCore <- getSpockHeart
|
|
|
|
- maybeWorlds <- liftIO $ mapConcurrently (\_ -> runSQL spockCore) ([1..queries] :: [Int])
|
|
|
|
- json $ catMaybes maybeWorlds
|
|
|
|
- -- | Test 4: Fortunes
|
|
|
|
- get "fortune" $
|
|
|
|
- do liftIO $ putStrLn "test"
|
|
|
|
- -- | Test 6: Plain text
|
|
|
|
- get "plaintext" $
|
|
|
|
- text "Hello, World!"
|
|
|
|
|
|
+ runSpock 3000 $ spock (defaultSpockCfg Nothing dbConn ()) $ do
|
|
|
|
+ -- | Test 1: JSON serialization
|
|
|
|
+ get "json" $
|
|
|
|
+ json $ Object (fromList [("message", "Hello, World!")])
|
|
|
|
+ -- | Test 2: Single database query
|
|
|
|
+ get "db" $ do
|
|
|
|
+ rand <- liftIO $ randomRIO (1, 10000)
|
|
|
|
+ maybeWorld <- runQuery $ fetchWorldById rand
|
|
|
|
+ case maybeWorld of
|
|
|
|
+ Just w -> json w
|
|
|
|
+ Nothing -> setStatus status404 >> text "World not found."
|
|
|
|
+ -- | Test 3: Multiple database queries
|
|
|
|
+ get "queries" $ do
|
|
|
|
+ queries <- max 1 . min 500 <$> param' "queries"
|
|
|
|
+ let runSQL core = runSpockIO core . runQuery . fetchWorldById =<< randomRIO (1, 10000)
|
|
|
|
+ spockCore <- getSpockHeart
|
|
|
|
+ maybeWorlds <- liftIO $ mapConcurrently (\_ -> runSQL spockCore) ([1..queries] :: [Int])
|
|
|
|
+ json $ catMaybes maybeWorlds
|
|
|
|
+ -- | Test 4: Fortunes
|
|
|
|
+ get "fortune" $ do
|
|
|
|
+ fortunes <- runQuery fetchFortunes
|
|
|
|
+ let newFortune = Fortune 0 "Additional fortune added at request time."
|
|
|
|
+ sortedFortunes = sort (newFortune : fortunes)
|
|
|
|
+ blaze $ renderFortunes sortedFortunes
|
|
|
|
+ -- | Test 5: Database Updates
|
|
|
|
+ -- todo
|
|
|
|
+
|
|
|
|
+ -- | Test 6: Plain text
|
|
|
|
+ get "plaintext" $
|
|
|
|
+ text "Hello, World!"
|