我正在努力使用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接收输入,解析它们并将其推送到processIncomingMessages
。 chan
从processOutgoingMessages
读取,运行一些转换并将数据发送到不同的网络API。这两个函数在处理传入/传出消息时与数据交互。
答案 0 :(得分:2)
是的,要运行SqlPersistM
,您需要runSqlite
。至于获得竞争条件,我认为这取决于sqlite本身。检查它是否允许并发访问。
由于forkIO
和其他异步内容仅适用于IO
,因此无法将SqlPersistM
拖入内部。好吧,因为它基本上是ReaderT
,你可能会,但我敢打赌,这不是它的意图。所以,IMO,你需要首先分叉线程,然后使用runSqlite
在内部运行持久性操作。