module Ecluse.Core.Worker.Liveness (
WorkerHeartbeat,
newWorkerHeartbeat,
newWorkerHeartbeatWithClock,
recordPoll,
lastPoll,
workerJobStepAllowance,
workerHeartbeatStaleAfter,
heartbeatHealthy,
Liveness (..),
alwaysLive,
heartbeatLivenessNow,
) where
import Data.Time (NominalDiffTime, UTCTime, diffUTCTime, getCurrentTime)
data WorkerHeartbeat = WorkerHeartbeat
{ WorkerHeartbeat -> UTCTime
whStartedAt :: UTCTime
, WorkerHeartbeat -> IO UTCTime
whNow :: IO UTCTime
, WorkerHeartbeat -> TVar (Maybe UTCTime)
whLastPoll :: TVar (Maybe UTCTime)
}
newWorkerHeartbeat :: IO WorkerHeartbeat
newWorkerHeartbeat :: IO WorkerHeartbeat
newWorkerHeartbeat = IO UTCTime -> IO WorkerHeartbeat
newWorkerHeartbeatWithClock IO UTCTime
getCurrentTime
newWorkerHeartbeatWithClock :: IO UTCTime -> IO WorkerHeartbeat
newWorkerHeartbeatWithClock :: IO UTCTime -> IO WorkerHeartbeat
newWorkerHeartbeatWithClock IO UTCTime
clock = do
startedAt <- IO UTCTime
clock
var <- newTVarIO Nothing
pure WorkerHeartbeat{whStartedAt = startedAt, whNow = clock, whLastPoll = var}
recordPoll :: WorkerHeartbeat -> UTCTime -> IO ()
recordPoll :: WorkerHeartbeat -> UTCTime -> IO ()
recordPoll WorkerHeartbeat
heartbeat UTCTime
now = STM () -> IO ()
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (TVar (Maybe UTCTime) -> Maybe UTCTime -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar (WorkerHeartbeat -> TVar (Maybe UTCTime)
whLastPoll WorkerHeartbeat
heartbeat) (UTCTime -> Maybe UTCTime
forall a. a -> Maybe a
Just UTCTime
now))
lastPoll :: WorkerHeartbeat -> IO (Maybe UTCTime)
lastPoll :: WorkerHeartbeat -> IO (Maybe UTCTime)
lastPoll = TVar (Maybe UTCTime) -> IO (Maybe UTCTime)
forall (m :: * -> *) a. MonadIO m => TVar a -> m a
readTVarIO (TVar (Maybe UTCTime) -> IO (Maybe UTCTime))
-> (WorkerHeartbeat -> TVar (Maybe UTCTime))
-> WorkerHeartbeat
-> IO (Maybe UTCTime)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WorkerHeartbeat -> TVar (Maybe UTCTime)
whLastPoll
workerJobStepAllowance :: NominalDiffTime
workerJobStepAllowance :: NominalDiffTime
workerJobStepAllowance = NominalDiffTime
300
workerHeartbeatStaleAfter :: NominalDiffTime
workerHeartbeatStaleAfter :: NominalDiffTime
workerHeartbeatStaleAfter = NominalDiffTime
2 NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
* NominalDiffTime
workerJobStepAllowance NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
+ NominalDiffTime
60
heartbeatHealthy :: UTCTime -> UTCTime -> Maybe UTCTime -> Bool
heartbeatHealthy :: UTCTime -> UTCTime -> Maybe UTCTime -> Bool
heartbeatHealthy UTCTime
now UTCTime
startedAt Maybe UTCTime
polledAt =
UTCTime -> UTCTime -> NominalDiffTime
diffUTCTime UTCTime
now (UTCTime -> Maybe UTCTime -> UTCTime
forall a. a -> Maybe a -> a
fromMaybe UTCTime
startedAt Maybe UTCTime
polledAt) NominalDiffTime -> NominalDiffTime -> Bool
forall a. Ord a => a -> a -> Bool
<= NominalDiffTime
workerHeartbeatStaleAfter
data Liveness = Liveness
{ Liveness -> Bool
liveHealthy :: Bool
, Liveness -> Maybe UTCTime
liveLastPoll :: Maybe UTCTime
}
deriving stock (Liveness -> Liveness -> Bool
(Liveness -> Liveness -> Bool)
-> (Liveness -> Liveness -> Bool) -> Eq Liveness
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Liveness -> Liveness -> Bool
== :: Liveness -> Liveness -> Bool
$c/= :: Liveness -> Liveness -> Bool
/= :: Liveness -> Liveness -> Bool
Eq, Int -> Liveness -> ShowS
[Liveness] -> ShowS
Liveness -> String
(Int -> Liveness -> ShowS)
-> (Liveness -> String) -> ([Liveness] -> ShowS) -> Show Liveness
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Liveness -> ShowS
showsPrec :: Int -> Liveness -> ShowS
$cshow :: Liveness -> String
show :: Liveness -> String
$cshowList :: [Liveness] -> ShowS
showList :: [Liveness] -> ShowS
Show)
alwaysLive :: Liveness
alwaysLive :: Liveness
alwaysLive = Liveness{liveHealthy :: Bool
liveHealthy = Bool
True, liveLastPoll :: Maybe UTCTime
liveLastPoll = Maybe UTCTime
forall a. Maybe a
Nothing}
heartbeatLivenessNow :: WorkerHeartbeat -> IO Liveness
heartbeatLivenessNow :: WorkerHeartbeat -> IO Liveness
heartbeatLivenessNow WorkerHeartbeat
heartbeat = do
now <- WorkerHeartbeat -> IO UTCTime
whNow WorkerHeartbeat
heartbeat
polledAt <- lastPoll heartbeat
pure Liveness{liveHealthy = heartbeatHealthy now (whStartedAt heartbeat) polledAt, liveLastPoll = polledAt}