我正在尝试在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)
{
..........................
}
答案 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"