4

我正在构建一个仆人应用程序,该应用程序使用通过获取 url 开始的摇动生成报告。直到请求记录东西,这就像一个魅力,但现在我遇到了一个问题。

一个处理程序start开始生成报告 - 因为这可能需要相当长的时间 - 我立即返回 200,并生成一个进程来完成实际工作,日志记录由logging-effect.

我的处理程序的简化版本start如下所示

start :: IO () -> App ()
start mkReport = do
  logInfo $ PP.text "Report generation started"
  _ <- liftIO . forkIO $ catch mkReport caught
  where caught e =  do logError $ PP.text "Report generation crashed: " <>
                     {-^^^^^^^-} (PP.text . T.pack $ displayException e)
                       cleanup
  return ()

AppMonadLog (WithTimestamp (WithSeverity Doc))- 所以logInfo工作正常。✔</p>

准确地说App是以下新类型:

newtype App a =
    App { _runApp :: ReaderT Environment (ExceptT ServantErr
                     (LoggingT (WithTimestamp (WithSeverity Doc)) IO)) a
        } deriving ( Functor, Applicative, Monad, MonadReader Environment,
                   , MonadError ServantErr, MonadLog (WithTimestamp (WithSeverity Doc)))

但是当我尝试logError在部件内部调用时caught- 除了cleanup删除生成/临时文件的操作之外,我得到一个编译器错误。✘</p>

No instance for MonadLog (WithSeverity Doc) IO arising from a use of 'logError'...

这是正确的,没有这样的实例IO,谢谢 ghc 告诉我这一点并且在运行时没有崩溃!

这些是我正在经历的想法-也许有人看到了错误的假设:

  • 我必须使用forkIOfork 报告生成?
  • 如果有类似的东西,forkIOish :: MonadIO m => m () -> m ThreadIdcatchIsh :: (MonadIO m, Exception e) => m a -> (e -> m a) -> m a 会帮助我吗?- 我认为是的 - 在我的情况下,我可以在内部liftIO调用时进行清理和 mkReport 部分。logErrorApp
  • 有没有办法在提升的部分中“解除”单子变压器堆栈的属性?
4

0 回答 0