Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I cause a WARP server to terminate?

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?

like image 945
Jean-Paul Calderone Avatar asked Aug 23 '17 12:08

Jean-Paul Calderone


1 Answers

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!"
like image 93
Michael Snoyman Avatar answered Sep 22 '22 02:09

Michael Snoyman