I have an HTTP application server that needs to exit when handling a certain request under certain conditions (in order to be restarted by a supervisor).
Given a main like:
import Network.Wai.Handler.Warp (run)
main :: IO ()
main = do
config <- readConfig
run (portNumber config) (makeApp config)
and a handler something like:
livenessServer1 :: UTCTime -> FilePath -> Server LivenessProbeAPI1
livenessServer1 initialModificationTime monitorPath = do
mtime <- liftIO $ getModificationTime monitorPath
case mtime == initialModificationTime of
True -> return $ Liveness initialModificationTime mtime
False -> throwError $ err500 { errBody = "File modified." }
How do I cause the process to end after delivering the 500 response?
I'm on my phone right now, so I can't type exact code for you. But the basic idea is to throw your Warp thread an async exception. That may sound complicated, but the easiest way to approach it is to use the race function from the async library. Something like this:
toExitVar <- newEmptyMVar
race warp (takeMVar toExitVar)
And then in your handler, when you want Warp to exit:
putMVar toExitVar ()
EDIT A day later and I'm back at my computer, here's a fully worked example:
#!/usr/bin/env stack
-- stack --resolver lts-9.0 script
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Network.Wai
import Network.Wai.Handler.Warp
import Network.HTTP.Types
import Control.Concurrent.Async
import Control.Concurrent.MVar
main :: IO ()
main = do
toDie <- newEmptyMVar
race_ (takeMVar toDie) $ run 3000 $ \req send ->
if pathInfo req == ["die"]
then do
putMVar toDie ()
send $ responseLBS status200 [] "Goodbye!"
else send $ responseLBS status200 [] "Still alive!"