Main.hs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. {-# LANGUAGE BangPatterns, OverloadedStrings #-}
  2. module Main where
  3. import Control.Applicative
  4. import Control.Monad
  5. import Control.Monad.IO.Class
  6. import Data.Aeson
  7. import Data.Configurator
  8. import Data.Int
  9. import Data.Text (Text)
  10. import Data.Pool
  11. import Database.MySQL.Simple
  12. import Database.MySQL.Simple.Result
  13. import Database.MySQL.Simple.QueryResults
  14. import Prelude hiding (lookup)
  15. import Snap.Core
  16. import Snap.Http.Server
  17. import System.Random
  18. import qualified Data.HashMap.Lazy as HM
  19. import qualified Data.ByteString.Char8 as B
  20. data RandQuery = RQ !Int !Int
  21. instance ToJSON RandQuery where
  22. toJSON (RQ i n) = object ["id" .= i, "randomNumber" .= n]
  23. instance QueryResults RandQuery where
  24. convertResults [fa, fb] [va, vb] = RQ a b
  25. where
  26. !a = convert fa va
  27. !b = convert fb vb
  28. convertResults fs vs = convertError fs vs 2
  29. main :: IO ()
  30. main = do
  31. db <- load [Required "cfg/db.cfg"]
  32. foos <- mapM (lookup db) ["host", "uname", "pword", "dbase", "dport"]
  33. let foos' = sequence foos
  34. maybe (putStrLn "No foo") dbSetup foos'
  35. dbSetup :: [String] -> IO ()
  36. dbSetup sets = do
  37. pool <- createPool (connect $ getConnInfo sets) close 1 10 50
  38. httpServe config $ site pool
  39. config :: Config Snap a
  40. config = setAccessLog ConfigNoLog
  41. . setErrorLog ConfigNoLog
  42. . setPort 8000
  43. $ defaultConfig
  44. getConnInfo :: [String] -> ConnectInfo
  45. getConnInfo [host, user, pwd, db, port] = defaultConnectInfo
  46. { connectHost = host
  47. , connectUser = user
  48. , connectPassword = pwd
  49. , connectDatabase = db
  50. , connectPort = read port
  51. }
  52. getConnInfo _ = defaultConnectInfo
  53. site :: Pool Connection -> Snap ()
  54. site pool = route
  55. [ ("json", jsonHandler)
  56. , ("db", dbHandler pool)
  57. , ("dbs", dbsHandler pool)
  58. , ("plaintext", plaintextHandler pool)
  59. ]
  60. jsonHandler :: Snap ()
  61. jsonHandler = do
  62. modifyResponse (setContentType "application/json")
  63. writeLBS $ encode ( Object $ HM.singleton "message" (String "Hello, World!") )
  64. dbHandler :: Pool Connection -> Snap ()
  65. dbHandler pool = do
  66. modifyResponse (setContentType "application/json")
  67. r <- liftIO $ randomRIO (1, 10000)
  68. qry <- liftIO $ withResource pool (flip runOne r)
  69. writeLBS $ encode qry
  70. dbsHandler :: Pool Connection -> Snap ()
  71. dbsHandler pool = do
  72. modifyResponse (setContentType "application/json")
  73. qs <- getQueryParam "queries"
  74. runAll pool $ maybe 1 fst (qs >>= B.readInt)
  75. plaintextHandler :: Pool Connection -> Snap ()
  76. plaintextHandler pool = do
  77. modifyResponse (setContentType "text/plain")
  78. writeBS "Hello, World!"
  79. runAll :: Pool Connection -> Int -> Snap ()
  80. runAll pool i | i < 1 = runAll pool 1
  81. | i > 500 = runAll pool 500
  82. | otherwise = do
  83. !rs <- take i . randomRs (1, 10000) <$> liftIO newStdGen
  84. qry <- liftIO $ withResource pool (forM rs . runOne)
  85. writeLBS $ encode qry
  86. runOne :: Connection -> Int -> IO RandQuery
  87. runOne conn = fmap head . query conn "SELECT * FROM World where id=?" . Only