如何撰写forkIO和SqlPersistM

时间:2016-03-07 11:23:50

标签: haskell yesod

我正在努力使用DB动作(forkIO)来构建SqlPersistM的最佳方法。注意:SqlPersistM定义为here,基本上是ReaderT SqlBackend (NoLoggingT (ResourceT IO))。以下是有问题代码的简化版本:

startBot :: SqlPersistM ()
startBot = do
  chan <- liftIO newChan
  forkIO $ forever (processIncomingMessages chan) -- How to do do this?
  forkIO $ forever (processOutgoingMessages chan) -- And this?
  return ()

processIncomingMessages :: Chan -> SqlPersistM ()

processOutgoingMessages :: Chan -> SqlPersistM ()

main = runSqlite ":memory:" startBot

是否可以将内部分叉传递给SqlPersistM的{​​{1}}操作?或者应该将runSqlite动作放在fork中?前者会导致“竞争条件”排序吗?线程是否能够同步他们对底层数据库连接的使用?

更多上下文: runSqlite从网络API接收输入,解析它们并将其推送到processIncomingMessageschanprocessOutgoingMessages读取,运行一些转换并将数据发送到不同的网络API。这两个函数在处理传入/传出消息时与数据交互。

1 个答案:

答案 0 :(得分:2)

是的,要运行SqlPersistM,您需要runSqlite。至于获得竞争条件,我认为这取决于sqlite本身。检查它是否允许并发访问。

由于forkIO和其他异步内容仅适用于IO,因此无法将SqlPersistM拖入内部。好吧,因为它基本上是ReaderT,你可能会,但我敢打赌,这不是它的意图。所以,IMO,你需要首先分叉线程,然后使用runSqlite在内部运行持久性操作。