4

URLをGETすることで開始されたシェイクを使用してレポートを生成するサーバントアプリを構築しています。ものをログに記録するように要求されるまで、これは魅力的に機能していましたが、今は問題にぶつかっています。

1 つのハンドラー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 ()

AppのインスタンスであるMonadLog (WithTimestamp (WithSeverity Doc))ため、正常にlogInfo動作します。✔</p>

正確Appには、次の newtype です。

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!

これらは私が経験している考えです-誰かが間違った仮定を見ているかもしれません:

  • forkIOレポート生成をフォークするために使用する必要がありますか?
  • forkIOish :: MonadIO m => m () -> m ThreadIdのように機能するものがあれば、それはcatchIsh :: (MonadIO m, Exception e) => m a -> (e -> m a) -> m a 私を助けてくれますか? - はい、そう思います -私の場合、内部liftIOを呼び出している間にクリーンアップと mkReport の部分を実行できました。logErrorApp
  • 持ち上げられた部分のモナド変換スタックのプロパティを「持ち上げる」方法はありますか?
4

0 に答える 0