From 8a6a8459ab40055eecc882c7cc9b078f536b9a7a Mon Sep 17 00:00:00 2001 From: Puru Gupta Date: Tue, 4 Apr 2023 18:54:44 +0530 Subject: [PATCH] server: zero-downtime env vars update on cloud [GS-232]: https://hasurahq.atlassian.net/browse/GS-232?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8475 Co-authored-by: Anon Ray <616387+ecthiender@users.noreply.github.com> Co-authored-by: Naveen Naidu <30195193+Naveenaidu@users.noreply.github.com> GitOrigin-RevId: fb47f02f4e0d6d889c0348abc50fd46382f1bd5e --- server/src-lib/Hasura/Server/AppStateRef.hs | 55 +++++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/server/src-lib/Hasura/Server/AppStateRef.hs b/server/src-lib/Hasura/Server/AppStateRef.hs index 6af92024768..da994ee4c39 100644 --- a/server/src-lib/Hasura/Server/AppStateRef.hs +++ b/server/src-lib/Hasura/Server/AppStateRef.hs @@ -1,11 +1,10 @@ module Hasura.Server.AppStateRef ( -- * AppState - AppStateRef (..), - AppState (..), + AppStateRef, initialiseAppStateRef, withSchemaCacheUpdate, - readAppContextRef, - getRebuildableSchemaCacheWithVersion, + withAppContextUpdate, + updateAppStateRef, -- * TLS AllowList reference TLSAllowListRef, @@ -15,6 +14,8 @@ module Hasura.Server.AppStateRef -- * Utility getSchemaCache, getSchemaCacheWithVersion, + getRebuildableSchemaCacheWithVersion, + readAppContextRef, getAppContext, logInconsistentMetadata, ) @@ -204,3 +205,49 @@ updateMetadataVersionGauge :: MonadIO m => Gauge -> RebuildableSchemaCache -> m updateMetadataVersionGauge metadataVersionGauge schemaCache = do let metadataVersion = scMetadataResourceVersion . lastBuiltSchemaCache $ schemaCache liftIO $ Gauge.set metadataVersionGauge $ getMetadataResourceVersion metadataVersion + +-- | Set the 'RebuildableAppContext' to the 'AppStateRef' produced by the given +-- action. +-- +-- An internal lock ensures that at most one update to the 'AppStateRef' may +-- proceed at a time. +withAppContextUpdate :: + (MonadIO m, MonadBaseControl IO m) => + AppStateRef impl -> + m (a, RebuildableAppContext impl) -> + m a +withAppContextUpdate (AppStateRef lock cacheRef _) action = + withMVarMasked lock $ \() -> do + (!res, !newCtx) <- action + liftIO $ do + -- update app ctx in IO reference + modifyIORef' cacheRef $ \appState -> appState {asAppCtx = newCtx} + return res + +-- | Set the 'AppStateRef', atomically, to the ('RebuildableSchemaCache', +-- 'RebuildableAppContext') produced by the given action. +-- +-- An internal lock ensures that at most one update to the 'AppStateRef' may +-- proceed at a time. +updateAppStateRef :: + (MonadIO m, MonadBaseControl IO m) => + AppStateRef impl -> + L.Logger L.Hasura -> + RebuildableAppContext impl -> + RebuildableSchemaCache -> + m () +updateAppStateRef (AppStateRef lock cacheRef metadataVersionGauge) logger !newAppCtx !newSC = + withMVarMasked lock $ const do + liftIO do + -- update schemacache in IO reference + modifyIORef' cacheRef $ \appState -> + let !newVer = incSchemaCacheVer (snd $ asSchemaCache appState) + in appState {asSchemaCache = (newSC, newVer), asAppCtx = newAppCtx} + + -- update metric with new metadata version + updateMetadataVersionGauge metadataVersionGauge newSC + + let inconsistentObjectsList = scInconsistentObjs $ lastBuiltSchemaCache newSC + logInconsistentMetadata' = logInconsistentMetadata logger inconsistentObjectsList + -- log any inconsistent objects everytime this method is called + logInconsistentMetadata'