【问题标题】:Use Redis.Message from outside of the pubSub callback在 pubSub 回调之外使用 Redis.Message
【发布时间】:2021-06-07 14:56:48
【问题描述】:

documentation for Hedis中,给出了一个使用pubSub函数的例子:

pubSub :: PubSub -> (Message -> IO PubSub) -> Redis ()

pubSub (subscribe ["chat"]) $ \msg -> do
    putStrLn $ "Message from " ++ show (msgChannel msg)
    return $ unsubscribe ["chat"]

鉴于pubSub 返回一个Redis (),是否有可能在代码的更下方,从回调外部重用这个msg 消息?

我从在 ScottyM monad 中运行的 Scotty 端点调用 pubSub,并且应该返回(长话短说)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

或者,有没有办法在回调中使用 Scotty 的 json?到目前为止,我无法做到这一点。

【问题讨论】:

  • 是否应该将带有json 的行进一步向右缩进,使其位于 post 端点的 do 块中?

标签: haskell redis publish-subscribe scotty


【解决方案1】:

我假设您打算进一步缩进 json 行。

为此,您可以在 IO 中使用可变变量,例如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

编辑:我想我真的不知道 runRedis 函数是否在收到消息之前阻塞,如果不是这种情况,那么您可以使用 MVar 代替:

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

【讨论】:

  • 缩进的好点,我解决了这个问题
  • 非常有趣的答案,谢谢。这是唯一的方法吗?
  • fwiw,runRedis 在收到消息之前会一直阻塞
  • 我认为像这样在 IO 中使用可变变量是唯一的方法。理想情况下,该库应该包含可以返回值的 pubSub 函数的替代版本,但据我所知,情况并非如此。
  • 所以没有其他选择,比如使用转换器堆栈(或任何东西)从回调中调用json msg
猜你喜欢
  • 2021-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多