fix: catch IOExceptions in reReadRecipe and wrap watchDir callback for resilience
This commit is contained in:
+30
-17
@@ -1,4 +1,5 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
|
||||||
{- | WAI application for the Roux recipe server.
|
{- | WAI application for the Roux recipe server.
|
||||||
|
|
||||||
@@ -10,7 +11,7 @@ module Roux.Server (
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Concurrent (forkIO, threadDelay)
|
import Control.Concurrent (forkIO, threadDelay)
|
||||||
import Control.Exception (SomeException, catch)
|
import Control.Exception (IOException, SomeException, catch, try)
|
||||||
import Control.Monad (forever, when)
|
import Control.Monad (forever, when)
|
||||||
import Data.ByteString.Lazy (ByteString)
|
import Data.ByteString.Lazy (ByteString)
|
||||||
import Data.Char (toLower)
|
import Data.Char (toLower)
|
||||||
@@ -76,9 +77,16 @@ watchRecipes dir state = do
|
|||||||
let cfg = defaultConfig{confWatchMode = WatchModeOS}
|
let cfg = defaultConfig{confWatchMode = WatchModeOS}
|
||||||
withManagerConf cfg $ \mgr -> do
|
withManagerConf cfg $ \mgr -> do
|
||||||
_stopListening <- watchDir mgr dir (const True) $ \ev ->
|
_stopListening <- watchDir mgr dir (const True) $ \ev ->
|
||||||
when (eventIsDirectory ev == IsFile && ".cook" `isSuffixOf` eventPath ev) $ do
|
catch
|
||||||
let path = makeRelative dir (eventPath ev)
|
( do
|
||||||
reReadRecipe dir path state
|
when (eventIsDirectory ev == IsFile && ".cook" `isSuffixOf` eventPath ev) $ do
|
||||||
|
let path = makeRelative dir (eventPath ev)
|
||||||
|
reReadRecipe dir path state
|
||||||
|
)
|
||||||
|
( \e ->
|
||||||
|
putStrLn $
|
||||||
|
"[roux] watchDir callback error: " <> show (e :: SomeException)
|
||||||
|
)
|
||||||
-- Keep the thread alive (watchDir runs the callback on the manager thread)
|
-- Keep the thread alive (watchDir runs the callback on the manager thread)
|
||||||
forever $ threadDelay 1000000
|
forever $ threadDelay 1000000
|
||||||
|
|
||||||
@@ -89,22 +97,27 @@ reReadRecipe :: FilePath -> FilePath -> IORef (Map FilePath Idx.RecipeInfo) -> I
|
|||||||
reReadRecipe dir path state = do
|
reReadRecipe dir path state = do
|
||||||
let key = map toLower (stripCookExt path)
|
let key = map toLower (stripCookExt path)
|
||||||
let fullPath = dir </> path
|
let fullPath = dir </> path
|
||||||
exists <- doesFileExist fullPath
|
result <- try (doesFileExist fullPath)
|
||||||
if not exists
|
case result of
|
||||||
then do
|
Left (_ :: IOException) -> do
|
||||||
|
putStrLn $ "[roux] IO error checking " <> path <> ", skipping"
|
||||||
|
Right False -> do
|
||||||
atomicModifyIORef' state $ \m ->
|
atomicModifyIORef' state $ \m ->
|
||||||
(Map.delete key m, ())
|
(Map.delete key m, ())
|
||||||
putStrLn $ "[roux] removed " <> path
|
putStrLn $ "[roux] removed " <> path
|
||||||
else do
|
Right True -> do
|
||||||
info <- Idx.loadRecipe dir path
|
content <- try (Idx.loadRecipe dir path)
|
||||||
case Idx.riRecipe info of
|
case content of
|
||||||
Left err -> do
|
Left (_ :: IOException) -> do
|
||||||
putStrLn $ "[roux] parse error in " <> path <> ": " <> err
|
putStrLn $ "[roux] IO error reading " <> path <> ", keeping previous version"
|
||||||
putStrLn $ "[roux] keeping previous version"
|
Right info -> case Idx.riRecipe info of
|
||||||
Right _ -> do
|
Left err -> do
|
||||||
atomicModifyIORef' state $ \m ->
|
putStrLn $ "[roux] parse error in " <> path <> ": " <> err
|
||||||
(Map.insert key info m, ())
|
putStrLn $ "[roux] keeping previous version"
|
||||||
putStrLn $ "[roux] updated " <> path
|
Right _ -> do
|
||||||
|
atomicModifyIORef' state $ \m ->
|
||||||
|
(Map.insert key info m, ())
|
||||||
|
putStrLn $ "[roux] updated " <> path
|
||||||
|
|
||||||
-- | Route an incoming request to the appropriate handler.
|
-- | Route an incoming request to the appropriate handler.
|
||||||
handleRequest :: IORef (Map FilePath Idx.RecipeInfo) -> Wai.Application
|
handleRequest :: IORef (Map FilePath Idx.RecipeInfo) -> Wai.Application
|
||||||
|
|||||||
Reference in New Issue
Block a user