/
ezq.hs
75 lines (61 loc) · 2.18 KB
/
ezq.hs
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
module Main where
import System.Environment(getArgs)
import System.Time
import Text.Printf
import Text.Regex.Posix
import Data.Maybe
import Data.Either
import Control.Monad
import Control.Concurrent
import Text.JSON(decode, encode, Result(..))
import qualified Network.Shed.Httpd as Httpd
import qualified Network.URI as URI
import Data.Task.QueueSet(QueueSet)
import qualified Data.Task.QueueSet as QS
import Request
maybeLogRequest req = do
putStrLn $ printf "%s %s"
(Httpd.reqMethod req)
(URI.uriPath (Httpd.reqURI req))
main :: IO ()
main = do
getArgs >>= run >> return ()
where run [port] = realMain ((read port)::Int)
run [] = realMain 8080
run _ = error "ezq [port]"
realMain port = do
putStrLn $ printf "serving on port %d" port
-- Create a new MVar, curry it onto the dispatcher, then initialize
-- the server.
mq <- newMVar QS.empty
Httpd.initServer port (dispatch mq)
resp code = Httpd.Response code []
dispatch :: MVar (QueueSet String) -> Httpd.Request -> IO Httpd.Response
dispatch mq req = do
-- maybeLogRequest req
if path /= "/"
then return $ Httpd.Response 404 [] "invalid path"
else dispatch' mq req
where
path = URI.uriPath $ Httpd.reqURI req
dispatch' mq req =
case decode body of
Ok decoded -> execute decoded
Error what -> return $ resp 400 $ printf "invalid request: %s" what
where
body = Httpd.reqBody req
execute (GetRequest queues) = do
now <- getClockTime
modifyMVar mq $ \qs ->
case QS.getAny now queues qs of
Just (which, qs') ->
let ((queue, ident), task) = which in
return (qs', resp 200 (encode $ GetOk [(queue, ident, task)]))
Nothing -> return (qs, resp 200 "none")
execute (EditRequest ops) = do
modifyMVar mq $ \qs ->
case foldM applyOp qs ops of
Just qs' -> return (qs', resp 200 (encode EditOk))
Nothing -> return (qs, resp 400 "fail")
applyOp qs (Add queue task) = Just $ QS.add task queue qs
applyOp qs (Remove queue ident) = QS.done (queue, ident) qs