我正在开发一个Yesod应用程序,其中许多应用程序请求将导致从第三方API中获取数据。获取的数据只能在随后的请求中使用--也就是说,触发API回调的请求可以完成,而无需等待调用完成。
重要的是,一个给定的数据xyz
不能被获取和存储两次,但是应用程序的本质是,多个客户端通常会同时对xyz
感兴趣。如果我让每个应用程序线程查询数据库,查看是否已经获取了xyz
,我将开始看到与并发相关的问题,即使规模不大。即使我编写了一堆代码来处理与并发相关的完整性问题--这并不有趣,而且很难肯定我已经涵盖了所有情况--以这种方式滥用昂贵的数据库查询是不好的做法。
在我看来,一个很好的选择是让所有App线程发布请求(“确保获取了xyz数据”)到一个AMQP队列,一个或多个‘后台工作人员’类型的进程将订阅该队列。
在这条线中,Greg建议使用双包布局,其中两个包都有“我的持久层”作为依赖项。他提到,我可以使用符号链接或hs-source-dir
来避免维护“持久层”代码的两个副本。
在很高的层次上,格雷格的描述对我来说是非常有意义的,但是我对哈斯克尔来说还是比较陌生的,我担心我需要一段时间才能弄清楚这些细节。有人能给我更详细地解释一下吗?
它的另一部分是:您建议如何编写BackgroundJobs过程?除了Yesod的脚手架之外,我从来没有写过生产Haskell代码。我把它概括起来--我只需要写一个main
,在其中我将订阅消息队列,并在每条消息上执行我的标注/处理/存储--但是我是否需要担心例如手动分叉,以确保进程在等待呼叫结束时不会被阻塞?
非常感谢。
发布于 2013-06-22 00:42:00
我离开了起始块,使用Erik建议的一般方法--我刚刚在我的脚手架项目的.cabal文件中添加了第二个.cabal块。下面是对应的源文件(Erik的公式中的“daemon.hs
”):
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Import
import Yesod.Default.Config
import qualified Database.Persist
import qualified Database.Persist.Store as DPS (runPool, createPoolConfig, loadConfig, applyEnv)
import Settings
import Model
import Data.Conduit (runResourceT)
import Control.Monad.Logger (runStdoutLoggingT)
import Debug.Trace
import Data.Text as T
runQueries = do
res <- getBy $ UniqueFoo "bar"
trace ("\nresult: " ++ show res ++ "\n\n") $ return ()
main :: IO ()
main = do
conf <- (fromArgs parseExtra)
dbconf <- withYamlEnvironment "config/postgresql.yml" (appEnv conf)
DPS.loadConfig >>= DPS.applyEnv
p <- DPS.createPoolConfig (dbconf :: Settings.PersistConfig)
runStdoutLoggingT $ runResourceT $ DPS.runPool dbconf runQueries p
我把它建立在这个Yesod wiki条目上的第一个例子上--修改了,因此可执行文件需要一个环境标志。
发布于 2013-06-21 00:26:21
我有一个应用程序,它由一个webapp和一个单独的守护进程组成,它收集数据并将其插入到它与webapp共享的数据库中。
基本上,我在同一个源代码树中有所有的代码,并且有两个文件定义了main :: IO ()
,一个叫做webapp.hs
,另一个叫做daemon.hs
。然后,我让阴谋集团文件定义和构建两个独立的可执行文件。
不幸的是,我无法共享代码,因为它是我在日常工作中所做的一个内部项目。
https://stackoverflow.com/questions/17220511
复制相似问题