module Handler.Health where import Import import qualified Data.Aeson.Encode.Pretty as Aeson import qualified Data.Text.Lazy.Builder as Builder import qualified Data.UUID as UUID import qualified Data.Set as Set import Control.Concurrent.STM.Delay getHealthR :: Handler TypedContent getHealthR = do reportStore <- getsYesod appHealthReport healthReports' <- liftIO $ readTVarIO reportStore interval <- getsYesod $ view _appHealthCheckInterval case fromNullable healthReports' of Nothing -> do let Min (NTop minInterval) = ofoldMap1 (Min . NTop) $ impureNonNull interval delay <- for minInterval $ \minInterval' -> liftIO . newDelay . round $ toRational minInterval' * 1e6 waitResult <- atomically $ maybe (pure $ Left False) (fmap (const $ Left True) . waitDelay) delay <|> (fmap Right . assertM (not. Set.null) $ readTVar reportStore) case waitResult of Left False -> sendResponseStatus noContent204 () Left True -> sendResponseStatus internalServerError500 ("System is not generating HealthReports" :: Text) Right _ -> redirect HealthR Just healthReports -> do let (Max lastUpdated, Min status) = ofoldMap1 (Max *** Min . healthReportStatus) healthReports reportNextUpdate (lastCheck, classifyHealthReport -> kind) = fromMaybe 0 (interval kind) `addUTCTime` lastCheck Max nextUpdate = ofoldMap1 (Max . reportNextUpdate) healthReports instanceId <- getsYesod appInstanceID setWeakEtagHashable (instanceId, lastUpdated) expiresAt nextUpdate setLastModified lastUpdated let status' | HealthSuccess <- status = ok200 | otherwise = internalServerError500 sendResponseStatus status' <=< selectRep $ do provideRep . siteLayoutMsg MsgHealthReport $ do setTitleI MsgHealthReport [whamlet| $newline never