【问题标题】:Haskell: Testing connection availability N times with a delay (scotty to mongodb)Haskell:延迟测试连接可用性N次(从scotty到mongodb)
【发布时间】:2014-07-10 01:12:53
【问题描述】:

我对 scotty web 应用程序和 mongodb 服务以正确的顺序启动有一个愚蠢的问题。 我先使用 systemd 启动 mongodb,然后再启动 scotty web 应用程序。由于某种原因它不起作用。应用程序错误,来自 mongodb 驱动程序的 connect: does not exist (Connection refused) 表示连接尚未准备好。

所以我的问题。如何以 0.5 秒的间隔测试连接可用性说 3 次,然后才出现错误?

这是应用程序的主要功能

main :: IO ()
main = do
  pool <- createPool (runIOE $ connect $ host "127.0.0.1") close 1 300 5
  clearSessions pool
  let r = \x -> runReaderT x pool
  scottyT 3000 r r basal

basal :: ScottyD ()
basal = do
  middleware $ staticPolicy (noDots >-> addBase "static")
  notFound $ runSession
  routes

虽然应用服务是在 mongodb 服务之后排序的,但在应用启动期间与 mongodb 的连接仍然不可用。所以我得到了上面提到的错误。 这是 systemd 服务文件,以避免有关正确服务顺序的问题。

[Unit]
Description=Basal Web Application
Requires=mongodb.service
After=mongodb.service iptables.service network-online.target

[Service]
User=http
Group=http
WorkingDirectory=/srv/http/basal/
ExecStart=/srv/http/basal/bin/basal
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

我不知道为什么在正确的服务顺序下无法连接到 mongodb。 所以我想用 0.5 秒的延迟用 haskell 代码探测连接可用性三次,然后出错。我该怎么做?

谢谢。

【问题讨论】:

  • 嘿,如果你的 systemd 服务文件中有 After=mongodb.service,mongodb 应该真的准备好接受连接了。您是否介意告诉我您的发行版(如果这是您获得 mongo 服务文件的地方)或粘贴您的 mongodb 服务文件(以及告诉我是您自己编写的还是从某个地方获得的)。非常感谢。
  • @CameronNemo 抱歉回复晚了 - 长假。我的发行版是 Arch。上面的服务文件显然是我自己的。 mongodb 服务文件随包一起提供。我不再尝试修复实际的 systemd 优先级。我在应用程序级别解决了它,尝试连接几次,直到 mongodb 准备好。

标签: mongodb haskell systemd scotty


【解决方案1】:

我猜从您使用的函数来看,您使用的是 mongoDB 1.5.0 之类的东西。

这里,connectIOE monad 中返回一些东西,它是 ErrorTIOErrorIO 的别名。

所以最好的方法是使用ErrorT 提供的重试机制。由于它是MonadPlus 的一个实例,如果我们不关心检查具体错误,我们可以使用mplus

retryConnect :: Int -> Int -> Host -> IOE Pipe
retryConnect retries delayInMicroseconds host
    | retries > 0 =
            connect host `mplus`
                (liftIO (threadDelay delayInMicroseconds) >>
                   retryConnect (retries - 1) delayInMicroseconds host)
    | otherwise = connect host

threadDelay 来自Control.Concurrent)。

然后将connect替换为retryConnect 2 500000,它会在第一次失败后以500,000微秒的间隔(即0.5s)重试两次。

如果您确实想检查特定错误,请改用catchError 并检查错误以决定是吞下它还是重新抛出它。

【讨论】:

  • 谢谢你的例子。它现在无法编译,在threadDelay delayInMicroseconds 中给我一个类型错误预期类型:Control.Monad.Trans.Error.ErrorT IOError IO () 实际类型:IO () 我会在白天仔细看看它...
  • 好的。我只需要liftIOthreadDelay delayInMicroseconds 部分。它现在编译。谢谢你。让我检查一下它是否解决了我的问题并且一切正常......
  • 一切按预期工作。我很高兴。 )) 为了完全摆脱错误,我不得不将重试次数增加到 4 次,并将延迟增加到 1 秒。之后它工作正常。再次感谢。
  • 为这个错误道歉,我懒得先自己编译——我现在已经在修复中编辑了:-)
猜你喜欢
  • 1970-01-01
  • 2013-07-13
  • 2013-09-01
  • 2012-01-22
  • 2013-04-10
  • 2020-06-15
  • 1970-01-01
  • 2014-06-25
  • 2017-11-01
相关资源
最近更新 更多