In the documentation for Hedis, an example of using the pubSub
function is given:
pubSub :: PubSub -> (Message -> IO PubSub) -> Redis ()
pubSub (subscribe ["chat"]) $ \msg -> do
putStrLn $ "Message from " ++ show (msgChannel msg)
return $ unsubscribe ["chat"]
Given that pubSub
returns a Redis ()
, is it nevertheless possible to re-use this msg
message further down in the code, from outside the callback?
I'm calling pubSub
from a Scotty endpoint which runs in the ScottyM
monad, and should return (to keep a long story short) a json msg
myEndpoint :: ScottyM ()
myEndpoint =
post "/hello/world" $ do
data :: MyData <- jsonData
runRedis redisConn $ do
pubSub (subscribe ["channel"]) $ \msg -> do
doSomethingWith msg
return $ unsubscribe ["channel"]
-- how is it possible to retrieve `msg` from here?
json $ somethingBuiltFromMsg
Alternatively, is there a way to use Scotty's json
from within the callback? I haven't been able to do this so far.
I will assume you meant to indent the line with json
further.
You can use mutable variables in IO
for that, e.g. IORef
:
import Data.IORef (newIORef, writeIORef, readIORef)
import Control.Monad.IO.Class (liftIO)
myEndpoint :: ScottyM ()
myEndpoint =
post "/hello/world" $ do
data :: MyData <- jsonData
msgRef <- liftIO (newIORef Nothing)
runRedis redisConn $ do
pubSub (subscribe ["channel"]) $ \msg -> do
writeIORef msgRef (Just msg)
return $ unsubscribe ["channel"]
Just msg <- liftIO (readIORef msgRef)
json $ doSomethingWithMsg msg
Edit: I guess I don't really know if the runRedis function blocks until the message has been received, if that is not the case then you can use an MVar
instead:
import Control.Concurrent.MVar (putMVar, takeMVar, newEmptyMVar)
import Control.Monad.IO.Class (liftIO)
myEndpoint :: ScottyM ()
myEndpoint =
post "/hello/world" $ do
data :: MyData <- jsonData
msgVar <- liftIO newEmptyMVar
runRedis redisConn $ do
pubSub (subscribe ["channel"]) $ \msg -> do
putMVar msgVar msg
return $ unsubscribe ["channel"]
msg <- liftIO (takeMVar msgVar)
json $ doSomethingWithMsg msg