Reputation: 103
First some background, I have a requirement where I need to have a config that needs to be updated(by fetching from a Database or an API call) every 10 mins(for example a session token which expires every 10 mins) and it needs to be available to my web server app.
The solution I came up for this is to create a separate long-running thread which will keep on refreshing the config every 10 mins. I will create this thread during application start and need this thread to keep on running as long as the application is running. If this thread gets killed due to some exception, I need to automatically restart it so that it can keep in doing its job.
I tried using try
to handle any exceptions that might be thrown when my thread is killed, but it doesn't seem to detect or catch the exception.
Code I used:
restartableThread :: IO () -> IO ()
restartableThread action = do
result <- try (forkIO action)
case result of
Left (e :: SomeException) -> do
putStrLn $ "Thread killed due to: " ++ show e
-- Restart the thread after a delay
threadDelay 1000000 -- 1 second delay
restartableThread action
Right _ -> return ()
Is there any other way to make sure my thread doesn't get killed, and if it gets killed, it is restarted automatically?
I'm also open to other ideas for tackling this requirement.
Upvotes: 1
Views: 103
Reputation: 33569
Use try action
to catch exceptions thrown by action
.
try (forkIO action)
does not handle exceptions from the action, only exceptions from forking the action, which practically never happen.
This function forks a thread that repeats an action every 10 minutes, or retries with a short delay when the action fails.
startBgJob :: IO () -> IO ()
startBgJob = void (forkIO (forever (threadDelay tenminutes >> retry action)))
where
retry action = do
e <- try action
case e of
Left (_ :: SomeException) -> threadDelay onesecond >> retry action
Right () -> pure ()
tenminutes = 600 * onesecond
onesecond = 1000000
Upvotes: 0