保持后台进程在heroku

时间:2016-04-19 12:18:51

标签: haskell heroku rabbitmq backgroundworker background-process

我正在尝试在heroku上运行rabbitmq后台进程来从队列中挑选任务并处理它们。我正在使用AMQP haskell库,他们提供以下example(部分省略或简洁。

main = do
    --setup connection omitted
    --connect to queue, wait for messages
    consumeMsgs chan "myQueue" Ack myCallback
    --halts process so messages are taken off the queue until a key is presseed
    getLine -- wait for keypress
    closeConnection conn -- close connection after key
    putStrLn "connection closed"

这在本地工作正常,因为getLine会保持流程运行,直到您按下某个键。但是,当我将其部署到heroku时,进程将以

退出

2016-04-19T08:37:23.373087+00:00 app[worker.1]: worker: <stdin>: hGetChar: end of file

我从the accepted answer to this question想出这是因为为了通过ssh部署后台进程,您需要将/dev/null/重定向到发送stdin信号的EOF getLine这个过程。

在我们的情况下,由于此信号,main :: IO () main = do mvar <- newEmptyMVar conn <- setupConnection queueName <- pack <$> getEnv "QUEUE_NAME" chan <- openChannel conn consumeMsgs chan queueName Ack processMessage installHandler sigINT (Catch (cleanupConnection conn mvar)) Nothing putStrLn "Running forever, press ctrl c to exit" -- this blocks until sigint is recieved and the handler for SIGINT -- "fills" the mvar. once that is filled the process exits run <- takeMVar mvar case run of _ -> return () mixpanelConfig :: IO Config mixpanelConfig = liftM2 Config (ApiToken . pack <$> getEnv "MIXPANEL_API_TOKEN") (newManager tlsManagerSettings) cleanupConnection :: Connection -> MVar () -> IO () cleanupConnection conn mvar = do closeConnection conn putStrLn "SIGINT received.. closing rabbitmq connection" putMVar mvar () processMessage :: (Message, Envelope) -> IO () 函数退出,整个过程停止,阻止我们的工作人员熬夜。

部署时如何让这名工作人员继续运行?

编辑:最终解决方案 使用@carstons注释我最终得到了以下有效的实现:

void A::SetCallback(void (*callback)(int))
{
   .....................
}

void B::test()
{
   a->SetCallback(&B::Done); //
}

void B::Done(int i)
{
   ..........................
}

1 个答案:

答案 0 :(得分:1)

正如我在评论中指出的那样,如果你只想让它永远保持运行,你可以使用forever - 例如 - threadDelay

import Control.Concurrent (threadDelay)
import Control.Monad (forever)

main = do
    --setup connection omitted
    --connect to queue, wait for messages
    consumeMsgs chan "myQueue" Ack myCallback
    --halts process so messages are taken off the queue forever
    forever $ threadDelay 10000
    -- so this will never happen and you could remove it
    closeConnection conn -- close connection after key
    putStrLn "connection closed"

请注意,这当然不会真正关闭连接或退出应用程序 - 您必须终止该过程。

由于您需要一些消息/方式来向您的程序发送终止信号,因此替代方案会更复杂。

一种简单的方法是使用MVar,当您的队列收到某个停止 -message时,您可以在myCallback中设置这些内容:

import Control.Concurrent.MVar

main = do
    -- MVar to receve the quit-signal
    quitSignal <- newEmptyMVar
    --setup connection omitted
    --connect to queue, wait for messages - the callback should
    --set the quitSignal with putMVar quitSignal ()
    consumeMsgs chan "myQueue" Ack (myCallback quitSignal)
    --halts process so messages are taken off the queue till quitSignal
    takeMVar quitSignal
    -- so this will happen after quitSignal was set
    closeConnection conn -- close connection after key
    putStrLn "connection closed"