fix(jobs): cleaner shutdown of job-pool-manager

This commit is contained in:
Gregor Kleen 2019-09-26 11:56:33 +02:00
parent 98ff5ac303
commit adc8d466ac
3 changed files with 48 additions and 10 deletions

View File

@ -380,7 +380,7 @@ develMain = runResourceT $ do
void . liftIO $ awaitTermination `race` runSettings wsettings app
-- | The @main@ function for an executable running this site.
appMain :: forall m. MonadUnliftIO m => m ()
appMain :: forall m. (MonadUnliftIO m, MonadMask m) => m ()
appMain = runResourceT $ do
settings <- getAppSettings
@ -472,7 +472,7 @@ appMain = runResourceT $ do
foundationStoreNum :: Word32
foundationStoreNum = 2
getApplicationRepl :: (MonadResource m, MonadUnliftIO m) => m (Int, UniWorX, Application)
getApplicationRepl :: (MonadResource m, MonadUnliftIO m, MonadMask m) => m (Int, UniWorX, Application)
getApplicationRepl = do
settings <- getAppDevSettings
foundation <- makeFoundation settings

View File

@ -86,6 +86,7 @@ instance Exception JobQueueException
handleJobs :: ( MonadResource m
, MonadLogger m
, MonadUnliftIO m
, MonadMask m
)
=> UniWorX -> m ()
-- | Spawn a set of workers that read control commands from `appJobCtl` and address them as they come in
@ -97,7 +98,7 @@ handleJobs foundation@UniWorX{..}
| otherwise = do
UnliftIO{..} <- askUnliftIO
jobPoolManager <- allocateLinkedAsync . unliftIO $ manageJobPool foundation
jobPoolManager <- allocateLinkedAsyncWithUnmask $ \unmask -> unliftIO $ manageJobPool foundation unmask
jobCron <- allocateLinkedAsync . unliftIO $ manageCrontab foundation
@ -129,15 +130,32 @@ manageJobPool :: forall m.
( MonadResource m
, MonadLogger m
, MonadUnliftIO m
, MonadMask m
)
=> UniWorX -> m ()
manageJobPool foundation@UniWorX{..}
= flip runContT return . forever . join . atomically $ asum
[ spawnMissingWorkers
, reapDeadWorkers
, terminateGracefully
]
=> UniWorX -> (forall a. IO a -> IO a) -> m ()
manageJobPool foundation@UniWorX{..} unmask = shutdownOnException $
flip runContT return . forever . join . atomically $ asum
[ spawnMissingWorkers
, reapDeadWorkers
, terminateGracefully
]
where
shutdownOnException :: m a -> m a
shutdownOnException act = do
UnliftIO{..} <- askUnliftIO
actAsync <- allocateLinkedAsyncMasked $ unliftIO act
let handleExc e = do
atomically $ do
jState <- tryReadTMVar appJobState
for_ jState $ \JobState{jobShutdown} -> tryPutTMVar jobShutdown ()
void $ wait actAsync
throwM e
unmask (wait actAsync) `catchAll` handleExc
num :: Int
num = fromIntegral $ foundation ^. _appJobWorkers

View File

@ -1,5 +1,7 @@
module UnliftIO.Async.Utils
( allocateAsync, allocateLinkedAsync
, allocateAsyncWithUnmask, allocateLinkedAsyncWithUnmask
, allocateAsyncMasked, allocateLinkedAsyncMasked
) where
import ClassyPrelude hiding (cancel, async, link)
@ -17,3 +19,21 @@ allocateAsync = fmap (view _2) . flip allocate cancel . liftIO . async
allocateLinkedAsync :: forall m a. (MonadUnliftIO m, MonadResource m) => IO a -> m (Async a)
allocateLinkedAsync = uncurry (<$) . (id &&& link) <=< allocateAsync
allocateAsyncWithUnmask :: forall m a.
MonadResource m
=> ((forall b. IO b -> IO b) -> IO a) -> m (Async a)
allocateAsyncWithUnmask act = fmap (view _2) . flip allocate cancel . liftIO $ asyncWithUnmask act
allocateLinkedAsyncWithUnmask :: forall m a. (MonadUnliftIO m, MonadResource m) => ((forall b. IO b -> IO b) -> IO a) -> m (Async a)
allocateLinkedAsyncWithUnmask act = uncurry (<$) . (id &&& link) =<< allocateAsyncWithUnmask act
allocateAsyncMasked :: forall m a.
MonadResource m
=> IO a -> m (Async a)
allocateAsyncMasked act = fmap (view _2) . flip allocate cancel . liftIO $ asyncWithUnmask (const act)
allocateLinkedAsyncMasked :: forall m a. (MonadUnliftIO m, MonadResource m) => IO a -> m (Async a)
allocateLinkedAsyncMasked = uncurry (<$) . (id &&& link) <=< allocateAsyncMasked