我想为我的webapp实现'graceful shutdown'命令(而不是我的第一直觉,就是要求人们杀死进程)
我的前两次尝试包括
liftIO exitSuccessE.yield (responseLBS statusOK [G.contentType "text/plain"] "") E.EOF两者都只是愉快地将结果返回给客户端并继续收听.应用程序可以做什么来杀死服务器?这甚至是一件合理的事情吗?
我承认我对iteratee没有很强的理解,只知道我可以消耗我的输入并且Iteratee是一个MonadIO实例.
Nat*_*ell 12
exitImmediately.拆除过程的最快方法之一,也非常讨厌调试.我不相信终结器/括号/最后块会在下降的过程中调用,具体取决于您的应用程序可能会破坏状态.Warp.run不捕获异常,所以这通过允许主线程(和仅主线程)上的默认异常处理程序来终止进程.正如其他人所提到的,使用MVar可能是最好的选择.为了完整起见,我把其他人包括在内,但他们确实有自己的位置.throwTo在基础库中使用了一些,我已经在一些使用C等价物的应用程序上工作exitImmediately:exit()虽然我没有遇到任何使用这种方法的Haskell应用程序.
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE OverloadedStrings #-}
module Main (main) where
import Control.Concurrent (MVar, ThreadId, forkIO, myThreadId, newEmptyMVar, putMVar, takeMVar)
import Control.Exception (Exception, throwTo)
import Control.Monad.Trans (liftIO)
import Data.ByteString (ByteString)
import Data.Data (Data, Typeable)
import Data.Enumerator (Iteratee)
import Network.HTTP.Types
import Network.Wai as Wai
import Network.Wai.Handler.Warp as Warp
import System.Exit (ExitCode (ExitSuccess))
import System.Posix.Process (exitImmediately)
data Shutdown = Shutdown deriving (Data, Typeable, Show)
instance Exception Shutdown
app :: ThreadId -> MVar () -> Request -> Iteratee ByteString IO Response
app mainThread shutdownMVar Request{pathInfo = pathInfo} = do
liftIO $ case pathInfo of
["shutdownByThrowing"] -> throwTo mainThread Shutdown
["shutdownByMVar"] -> putMVar shutdownMVar ()
["shutdownByExit"] -> exitImmediately ExitSuccess
_ -> return ()
return $ responseLBS statusOK [headerContentType "text/plain"] "ok"
main :: IO ()
main = do
mainThread <- myThreadId
shutdownMVar <- newEmptyMVar
forkIO $ Warp.run 3000 (app mainThread shutdownMVar)
takeMVar shutdownMVar
Run Code Online (Sandbox Code Playgroud)