3

我想创建一个可以从尽可能多的错误中恢复的函数,然后再试一次。当然,有意义的错误处理包含在程序的其他部分——这是保持运行的最后努力。所以我写了这个:

retryForever prog = catchAny prog progRetry
  where
    progRetry :: SomeException -> m a
    progRetry ex = do
      putStrLn $ pack $ show ex
      threadDelay 4000
      prog

然后我将我的主要 IO 操作包装在retryForever

main :: IO ()
main = retryForever $ do
  logger <- newLogger
  -- ...

在我程序的另一部分(可能是不同的绿色线程)中,我使用以下方法进行测试:

error "this is a TEST ERROR"

导致:

: this is a TEST ERROR
CallStack (from HasCallStack):
  error, called at XXXX

(并且程序死亡而不是继续)

请注意,我使用的是经典前奏,用于可能很重要的情况,例如catchAny不处理那里的异步异常,这很可能是这里的问题。

4

1 回答 1

5

当程序失败时,你应该prog再次运行程序,但是retryForever如果它再次失败,你应该继续尝试:

import Control.Monad.Catch(catchAll)

retryForever :: IO a -> IO a
retryForever prog = catchAll prog retry
  where retry ex = do
      putStrLn $ pack $ show ex
      threadDelay 4000
      retryForever prog
于 2019-08-23T21:29:18.930 回答