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 の部分を実行できました。logError
App
- 持ち上げられた部分のモナド変換スタックのプロパティを「持ち上げる」方法はありますか?