2023-03-17 13:29:07 +03:00
|
|
|
{-# LANGUAGE Arrows #-}
|
|
|
|
|
2023-02-24 21:09:36 +03:00
|
|
|
module Hasura.App.State
|
Clean `AppEnv` and `AppContext` passing, remove `RunT`, reduce `ServerConfigCtx` uses
## Description
This PR does several different things that happen to overlap; the most important being:
- it removes `RunT`: it was redundant in places where we already had `Handler`, and only used in one other place, `SchemaUpdate`, for which a local `SchemaUpdateT` is more than enough;
- it reduces the number of places where we create a `ServerConfigCtx`, since now `HasServerConfigCtx` can be implemented directly by `SchemaUpdateT` and `Handler` based on the full `AppContext`;
- it drastically reduces the number of arguments we pass around in the app init code, by introducing `HasAppEnv`;
- it simplifies `HandlerCtx` to reduce duplication
In doing so, this changes paves the way towards removing `ServerConfigCtx`, since there are only very few places where we construct it: we can now introduce smaller classes than `HasServerConfigCtx`, that expose only a relevant subset of fields, and implement them where we now implement `HasServerConfigCtx`.
This PR is loosely based on ideas in #8337, that are no longer applicable due to the changes introduced in #8159. A challenge of this PR was the postgres tests, which were running in `PGMetadataStorageAppT CacheBuild` :scream_cat:
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8392
GitOrigin-RevId: b90c1359066d20dbea329c87762ccdd1217b4d69
2023-03-21 13:44:21 +03:00
|
|
|
( -- * application state
|
|
|
|
RebuildableAppContext (..),
|
2023-03-17 13:29:07 +03:00
|
|
|
AppEnv (..),
|
2023-02-24 21:09:36 +03:00
|
|
|
AppContext (..),
|
|
|
|
Loggers (..),
|
Clean `AppEnv` and `AppContext` passing, remove `RunT`, reduce `ServerConfigCtx` uses
## Description
This PR does several different things that happen to overlap; the most important being:
- it removes `RunT`: it was redundant in places where we already had `Handler`, and only used in one other place, `SchemaUpdate`, for which a local `SchemaUpdateT` is more than enough;
- it reduces the number of places where we create a `ServerConfigCtx`, since now `HasServerConfigCtx` can be implemented directly by `SchemaUpdateT` and `Handler` based on the full `AppContext`;
- it drastically reduces the number of arguments we pass around in the app init code, by introducing `HasAppEnv`;
- it simplifies `HandlerCtx` to reduce duplication
In doing so, this changes paves the way towards removing `ServerConfigCtx`, since there are only very few places where we construct it: we can now introduce smaller classes than `HasServerConfigCtx`, that expose only a relevant subset of fields, and implement them where we now implement `HasServerConfigCtx`.
This PR is loosely based on ideas in #8337, that are no longer applicable due to the changes introduced in #8159. A challenge of this PR was the postgres tests, which were running in `PGMetadataStorageAppT CacheBuild` :scream_cat:
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8392
GitOrigin-RevId: b90c1359066d20dbea329c87762ccdd1217b4d69
2023-03-21 13:44:21 +03:00
|
|
|
|
|
|
|
-- * env access
|
|
|
|
HasAppEnv (..),
|
|
|
|
|
|
|
|
-- * init functions
|
2023-03-17 13:29:07 +03:00
|
|
|
buildRebuildableAppContext,
|
2023-03-30 19:31:50 +03:00
|
|
|
rebuildRebuildableAppContext,
|
Remove `HasServerConfigCtx` from the schema cache build.
## Description
This PR is a incremental step towards achieving the goal of #8344. It is a less ambitious version of #8484.
This PR removes all references to `HasServerConfigCtx` from the cache build and removes `ServerConfigCtx` from `CacheBuildParams`, making `ServerConfigCtx` an argument being passed around manually instead. This has several benefits: by making it an arrow argument, we now properly integrate the fields that change over time in the dependency framework, as they should be, and we can clean up some of the top-level app code.
## Implementation
In practice, this PR introduces a `HasServerConfigCtx` instance for `CacheRWT`, the monad we use to build the cache, so we can retrieve the `ServerConfigCtx` in the implementation of `CacheRWM`. This contributes to reducing the amount of `HasServerConfigCtx` in the code: we can remove `SchemaUpdateT` altogether, and we can remove the `HasServerConfigCtx` instance of `Handler`. This makes `HasServerConfigCtx` almost **an implementation detail of the Metadata API**.
This first step is enough to achieve the goal of #8344: we can now build the schema cache in the app monad, since we no longer rely on `HasServerConfigCtx` to build it.
## Drawbacks
This PR does not attempt to remove the use of `ServerConfigCtx` itself in the schema cache build: doing so would make this PR much much bigger. Ideally, to avoid having all the static fields given as arrow-ish arguments to the cache, we could depend on `HasAppEnv` in the cache build, and use `AppContext` as an arrow argument. But making the cache build depend on the full `AppEnv` and `AppContext` creates a lot of circular imports; and since removing `ServerConfigCtx` itself isn't required to achieve #8344, this PR keeps it wholesale and defers cleaning it to a future PR.
A negative consequence of this is that we need an `Eq` instance on `ServerConfigCtx`, and that instance is inelegant.
## Future work
There are several further steps we can take in parallel after this is merged. First, again, we can make a new version of #8344, removing `CacheBuild`, FINALLY. As for `ServerConfigCtx`, we can split it / rename it to make ad-hoc structures. If it turns out that `ServerConfigCtx` is only ever used for the schema cache build, we could split it between `CacheBuildEnv` and `CacheBuildContext`, which will be subsets of `AppEnv` and `AppContext`, avoiding import loops.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8509
GitOrigin-RevId: 01b37cc3fd3490d6b117701e22fc4ac88b62b6b5
2023-03-27 20:42:37 +03:00
|
|
|
|
Remove `ServerConfigCtx`.
### Description
This PR removes `ServerConfigCtx` and `HasServerConfigCtx`. Instead, it favours different approaches:
- when the code was only using one field, it passes that field explicitly (usually `SQLGenCtx` or `CheckFeatureFlag`)
- when the code was using several fields, but in only one function, it inlines
- for the cache build, it introduces `CacheStaticConfig` and `CacheDynamicConfig`, which are subsets of `AppEnv` and `AppContext` respectively
The main goal of this is to help with the modularization of the engine: as `ServerConfigCtx` had fields whose types were imported from several unrelated parts of the engine, using it tied together parts of the engine that should not be aware of one another (such as tying together `Hasura.LogicalModel` and `Hasura.GraphQL.Schema`).
The bulk of this PR is a change to the cache build, as a follow up to #8509: instead of giving the entire `ServerConfigCtx` as a incremental rule argument, we only give the new `CacheDynamicConfig` struct, which has fewer fields. The other required fields, that were coming from the `AppEnv`, are now given via the `HasCacheStaticConfig` constraint, which is a "subset" of `HasAppEnv`.
(Some further work could include moving `StringifyNumbers` out of `GraphQL.Schema.Options`, given how it is used all across the codebase, including in `RQL.DML`.)
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8513
GitOrigin-RevId: 818cbcd71494e3cd946b06adbb02ca328a8a298e
2023-04-04 18:59:58 +03:00
|
|
|
-- * subsets
|
|
|
|
initSQLGenCtx,
|
|
|
|
buildCacheStaticConfig,
|
|
|
|
buildCacheDynamicConfig,
|
2023-02-24 21:09:36 +03:00
|
|
|
)
|
|
|
|
where
|
|
|
|
|
2023-03-17 13:29:07 +03:00
|
|
|
import Control.Arrow.Extended
|
2023-02-24 21:09:36 +03:00
|
|
|
import Control.Concurrent.STM qualified as STM
|
2023-03-17 13:29:07 +03:00
|
|
|
import Control.Monad.Trans.Control (MonadBaseControl)
|
|
|
|
import Data.Environment qualified as E
|
|
|
|
import Data.HashSet qualified as Set
|
2023-02-24 21:09:36 +03:00
|
|
|
import Database.PG.Query qualified as PG
|
2023-04-05 11:57:19 +03:00
|
|
|
import Hasura.Backends.DataConnector.Agent.Client (AgentLicenseKey)
|
2023-03-17 13:29:07 +03:00
|
|
|
import Hasura.Base.Error
|
2023-04-05 11:57:19 +03:00
|
|
|
import Hasura.CredentialCache
|
2023-02-24 21:09:36 +03:00
|
|
|
import Hasura.Eventing.Common (LockedEventsCtx)
|
2023-03-17 13:29:07 +03:00
|
|
|
import Hasura.Eventing.EventTrigger
|
2023-02-24 21:09:36 +03:00
|
|
|
import Hasura.GraphQL.Execute.Subscription.Options
|
|
|
|
import Hasura.GraphQL.Execute.Subscription.State qualified as ES
|
2023-03-17 13:29:07 +03:00
|
|
|
import Hasura.Incremental qualified as Inc
|
2023-02-24 21:09:36 +03:00
|
|
|
import Hasura.Logging qualified as L
|
|
|
|
import Hasura.Prelude
|
Remove `ServerConfigCtx`.
### Description
This PR removes `ServerConfigCtx` and `HasServerConfigCtx`. Instead, it favours different approaches:
- when the code was only using one field, it passes that field explicitly (usually `SQLGenCtx` or `CheckFeatureFlag`)
- when the code was using several fields, but in only one function, it inlines
- for the cache build, it introduces `CacheStaticConfig` and `CacheDynamicConfig`, which are subsets of `AppEnv` and `AppContext` respectively
The main goal of this is to help with the modularization of the engine: as `ServerConfigCtx` had fields whose types were imported from several unrelated parts of the engine, using it tied together parts of the engine that should not be aware of one another (such as tying together `Hasura.LogicalModel` and `Hasura.GraphQL.Schema`).
The bulk of this PR is a change to the cache build, as a follow up to #8509: instead of giving the entire `ServerConfigCtx` as a incremental rule argument, we only give the new `CacheDynamicConfig` struct, which has fewer fields. The other required fields, that were coming from the `AppEnv`, are now given via the `HasCacheStaticConfig` constraint, which is a "subset" of `HasAppEnv`.
(Some further work could include moving `StringifyNumbers` out of `GraphQL.Schema.Options`, given how it is used all across the codebase, including in `RQL.DML`.)
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8513
GitOrigin-RevId: 818cbcd71494e3cd946b06adbb02ca328a8a298e
2023-04-04 18:59:58 +03:00
|
|
|
import Hasura.RQL.DDL.Schema.Cache.Config
|
2023-02-24 21:09:36 +03:00
|
|
|
import Hasura.RQL.Types.Common
|
|
|
|
import Hasura.RQL.Types.Metadata
|
2023-05-17 17:02:09 +03:00
|
|
|
import Hasura.RQL.Types.NamingCase
|
2023-04-24 11:50:29 +03:00
|
|
|
import Hasura.RQL.Types.Roles (RoleName)
|
2023-04-24 18:17:15 +03:00
|
|
|
import Hasura.RQL.Types.Schema.Options qualified as Options
|
2023-02-24 21:09:36 +03:00
|
|
|
import Hasura.RQL.Types.SchemaCache (MetadataResourceVersion)
|
2023-03-17 13:29:07 +03:00
|
|
|
import Hasura.Server.Auth
|
2023-02-28 12:09:31 +03:00
|
|
|
import Hasura.Server.Cors qualified as Cors
|
2023-02-24 21:09:36 +03:00
|
|
|
import Hasura.Server.Init
|
|
|
|
import Hasura.Server.Logging
|
|
|
|
import Hasura.Server.Metrics
|
|
|
|
import Hasura.Server.Prometheus
|
|
|
|
import Hasura.Server.Types
|
|
|
|
import Hasura.ShutdownLatch
|
|
|
|
import Hasura.Tracing qualified as Tracing
|
|
|
|
import Network.HTTP.Client qualified as HTTP
|
2023-02-28 12:09:31 +03:00
|
|
|
import Network.Wai.Handler.Warp (HostPreference)
|
|
|
|
import Network.WebSockets.Connection qualified as WebSockets
|
2023-03-17 13:29:07 +03:00
|
|
|
import Refined (NonNegative, Refined)
|
2023-02-24 21:09:36 +03:00
|
|
|
|
Clean `AppEnv` and `AppContext` passing, remove `RunT`, reduce `ServerConfigCtx` uses
## Description
This PR does several different things that happen to overlap; the most important being:
- it removes `RunT`: it was redundant in places where we already had `Handler`, and only used in one other place, `SchemaUpdate`, for which a local `SchemaUpdateT` is more than enough;
- it reduces the number of places where we create a `ServerConfigCtx`, since now `HasServerConfigCtx` can be implemented directly by `SchemaUpdateT` and `Handler` based on the full `AppContext`;
- it drastically reduces the number of arguments we pass around in the app init code, by introducing `HasAppEnv`;
- it simplifies `HandlerCtx` to reduce duplication
In doing so, this changes paves the way towards removing `ServerConfigCtx`, since there are only very few places where we construct it: we can now introduce smaller classes than `HasServerConfigCtx`, that expose only a relevant subset of fields, and implement them where we now implement `HasServerConfigCtx`.
This PR is loosely based on ideas in #8337, that are no longer applicable due to the changes introduced in #8159. A challenge of this PR was the postgres tests, which were running in `PGMetadataStorageAppT CacheBuild` :scream_cat:
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8392
GitOrigin-RevId: b90c1359066d20dbea329c87762ccdd1217b4d69
2023-03-21 13:44:21 +03:00
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- application state
|
|
|
|
|
2023-02-24 21:09:36 +03:00
|
|
|
{- Note [Hasura Application State]
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Hasura Application state represents the entire state of hasura.
|
|
|
|
|
|
|
|
Hasura Application State = AppEnv (static) + AppContext (dynamic)
|
|
|
|
|
|
|
|
Hasura Application State can be divided into two parts:
|
|
|
|
|
|
|
|
1. Read-Only State (Static State):
|
|
|
|
=================================
|
|
|
|
The information required to build this state is provided only during the
|
|
|
|
initialization of hasura. This information is immutable. If you want update any
|
|
|
|
field in this state, you would need to shutdown the current instance and
|
|
|
|
re-launch hausura with new information.
|
|
|
|
|
|
|
|
Eg: If you want to run hasura in read-only mode, you would have to mention
|
|
|
|
this information when hasura starts up. There is no way to make hasura
|
|
|
|
run in read-only mode once it has booted up.
|
|
|
|
|
|
|
|
2. Runtime Configurable State (Dynamic State):
|
|
|
|
==============================================
|
|
|
|
The information present in this state can be updated during the runtime. This state
|
|
|
|
is mutable and does not require a restart of hasura instance to take effect.
|
|
|
|
|
|
|
|
The fields in the state are usually updated via Metadata API's or Hasura Console.
|
|
|
|
|
|
|
|
Eg: You can change the entries in Allowlist via console and hasura need not restart
|
|
|
|
for the changes to take effect.
|
|
|
|
|
|
|
|
-}
|
|
|
|
|
2023-03-17 13:29:07 +03:00
|
|
|
data RebuildableAppContext impl = RebuildableAppContext
|
|
|
|
{ lastBuiltAppContext :: AppContext,
|
|
|
|
_racInvalidationMap :: InvalidationKeys,
|
|
|
|
_racRebuild :: Inc.Rule (ReaderT (L.Logger L.Hasura, HTTP.Manager) (ExceptT QErr IO)) (ServeOptions impl, E.Environment, InvalidationKeys) AppContext
|
|
|
|
}
|
|
|
|
|
2023-02-24 21:09:36 +03:00
|
|
|
-- | Represents the Read-Only Hasura State, these fields are immutable and the state
|
|
|
|
-- cannot be changed during runtime.
|
|
|
|
data AppEnv = AppEnv
|
2023-02-28 12:09:31 +03:00
|
|
|
{ appEnvPort :: Port,
|
|
|
|
appEnvHost :: HostPreference,
|
|
|
|
appEnvMetadataDbPool :: PG.PGPool,
|
2023-05-02 16:58:58 +03:00
|
|
|
appEnvIntrospectionDbPool :: Maybe PG.PGPool,
|
2023-02-24 21:09:36 +03:00
|
|
|
appEnvManager :: HTTP.Manager,
|
|
|
|
appEnvLoggers :: Loggers,
|
|
|
|
appEnvMetadataVersionRef :: STM.TMVar MetadataResourceVersion,
|
|
|
|
appEnvInstanceId :: InstanceId,
|
2023-02-28 12:09:31 +03:00
|
|
|
appEnvEnableMaintenanceMode :: MaintenanceMode (),
|
2023-02-24 21:09:36 +03:00
|
|
|
appEnvLoggingSettings :: LoggingSettings,
|
|
|
|
appEnvEventingMode :: EventingMode,
|
|
|
|
appEnvEnableReadOnlyMode :: ReadOnlyMode,
|
|
|
|
appEnvServerMetrics :: ServerMetrics,
|
|
|
|
appEnvShutdownLatch :: ShutdownLatch,
|
|
|
|
appEnvMetaVersionRef :: STM.TMVar MetadataResourceVersion,
|
|
|
|
appEnvPrometheusMetrics :: PrometheusMetrics,
|
|
|
|
appEnvTraceSamplingPolicy :: Tracing.SamplingPolicy,
|
|
|
|
appEnvSubscriptionState :: ES.SubscriptionsState,
|
|
|
|
appEnvLockedEventsCtx :: LockedEventsCtx,
|
2023-02-28 12:09:31 +03:00
|
|
|
appEnvConnParams :: PG.ConnParams,
|
|
|
|
appEnvTxIso :: PG.TxIsolation,
|
|
|
|
appEnvConsoleAssetsDir :: Maybe Text,
|
|
|
|
appEnvConsoleSentryDsn :: Maybe Text,
|
|
|
|
appEnvConnectionOptions :: WebSockets.ConnectionOptions,
|
|
|
|
appEnvWebSocketKeepAlive :: KeepAliveDelay,
|
|
|
|
appEnvWebSocketConnectionInitTimeout :: WSConnectionInitTimeout,
|
|
|
|
appEnvGracefulShutdownTimeout :: Refined NonNegative Seconds,
|
2023-03-30 19:31:50 +03:00
|
|
|
-- TODO: Move this to `AppContext`. We are leaving this for now as this cannot be changed directly
|
2023-03-17 13:29:07 +03:00
|
|
|
-- by the user on the cloud dashboard and will also require a refactor in HasuraPro/App.hs
|
|
|
|
-- as this thread is initialised there before creating the `AppStateRef`. But eventually we need
|
|
|
|
-- to do it for the Enterprise version.
|
|
|
|
appEnvSchemaPollInterval :: OptionalInterval,
|
2023-04-05 11:57:19 +03:00
|
|
|
appEnvCheckFeatureFlag :: CheckFeatureFlag,
|
|
|
|
appEnvLicenseKeyCache :: Maybe (CredentialCache AgentLicenseKey)
|
2023-02-24 21:09:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
-- | Represents the Dynamic Hasura State, these field are mutable and can be changed
|
|
|
|
-- during runtime.
|
|
|
|
data AppContext = AppContext
|
2023-03-17 13:29:07 +03:00
|
|
|
{ acAuthMode :: AuthMode,
|
2023-02-24 21:09:36 +03:00
|
|
|
acSQLGenCtx :: SQLGenCtx,
|
2023-03-17 13:29:07 +03:00
|
|
|
acEnabledAPIs :: Set.HashSet API,
|
2023-02-24 21:09:36 +03:00
|
|
|
acEnableAllowlist :: AllowListStatus,
|
|
|
|
acResponseInternalErrorsConfig :: ResponseInternalErrorsConfig,
|
2023-03-17 13:29:07 +03:00
|
|
|
acEnvironment :: E.Environment,
|
2023-02-24 21:09:36 +03:00
|
|
|
acRemoteSchemaPermsCtx :: Options.RemoteSchemaPermissions,
|
|
|
|
acFunctionPermsCtx :: Options.InferFunctionPermissions,
|
2023-03-17 13:29:07 +03:00
|
|
|
acExperimentalFeatures :: Set.HashSet ExperimentalFeature,
|
2023-02-28 12:09:31 +03:00
|
|
|
acDefaultNamingConvention :: NamingCase,
|
2023-02-24 21:09:36 +03:00
|
|
|
acMetadataDefaults :: MetadataDefaults,
|
|
|
|
acLiveQueryOptions :: LiveQueriesOptions,
|
2023-02-28 12:09:31 +03:00
|
|
|
acStreamQueryOptions :: StreamQueriesOptions,
|
2023-03-17 13:29:07 +03:00
|
|
|
acCorsPolicy :: Cors.CorsPolicy,
|
2023-02-28 12:09:31 +03:00
|
|
|
acConsoleStatus :: ConsoleStatus,
|
|
|
|
acEnableTelemetry :: TelemetryStatus,
|
2023-03-17 13:29:07 +03:00
|
|
|
acEventEngineCtx :: EventEngineCtx,
|
2023-02-28 12:09:31 +03:00
|
|
|
acAsyncActionsFetchInterval :: OptionalInterval,
|
2023-03-15 11:14:20 +03:00
|
|
|
acApolloFederationStatus :: ApolloFederationStatus
|
2023-02-24 21:09:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
-- | Collection of the LoggerCtx, the regular Logger and the PGLogger
|
|
|
|
data Loggers = Loggers
|
|
|
|
{ _lsLoggerCtx :: L.LoggerCtx L.Hasura,
|
|
|
|
_lsLogger :: L.Logger L.Hasura,
|
|
|
|
_lsPgLogger :: PG.PGLogger
|
|
|
|
}
|
2023-03-17 13:29:07 +03:00
|
|
|
|
|
|
|
data InvalidationKeys = InvalidationKeys
|
|
|
|
|
Clean `AppEnv` and `AppContext` passing, remove `RunT`, reduce `ServerConfigCtx` uses
## Description
This PR does several different things that happen to overlap; the most important being:
- it removes `RunT`: it was redundant in places where we already had `Handler`, and only used in one other place, `SchemaUpdate`, for which a local `SchemaUpdateT` is more than enough;
- it reduces the number of places where we create a `ServerConfigCtx`, since now `HasServerConfigCtx` can be implemented directly by `SchemaUpdateT` and `Handler` based on the full `AppContext`;
- it drastically reduces the number of arguments we pass around in the app init code, by introducing `HasAppEnv`;
- it simplifies `HandlerCtx` to reduce duplication
In doing so, this changes paves the way towards removing `ServerConfigCtx`, since there are only very few places where we construct it: we can now introduce smaller classes than `HasServerConfigCtx`, that expose only a relevant subset of fields, and implement them where we now implement `HasServerConfigCtx`.
This PR is loosely based on ideas in #8337, that are no longer applicable due to the changes introduced in #8159. A challenge of this PR was the postgres tests, which were running in `PGMetadataStorageAppT CacheBuild` :scream_cat:
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8392
GitOrigin-RevId: b90c1359066d20dbea329c87762ccdd1217b4d69
2023-03-21 13:44:21 +03:00
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- env access
|
|
|
|
|
|
|
|
-- | Provides access to the 'AppEnv'.
|
|
|
|
--
|
|
|
|
-- This class is nothing more than an equivalent of @MonadReader AppEnv m@, but
|
|
|
|
-- it abstracts it, so that application code can be written without explicitly
|
|
|
|
-- relying on an explicit implementation of the app monad. It allows for the app
|
|
|
|
-- env to be passed implicitly instead of explictly in all of the app init code.
|
|
|
|
--
|
|
|
|
-- This class is not meant to be used across the entirety of the codebase, as
|
|
|
|
-- using it brings in scope the types of all fields, creating dependencies
|
|
|
|
-- between unrelated parts of the codebase. It is only meant to be used at the
|
|
|
|
-- top level; more specific parts of the code should only rely on the relevant
|
|
|
|
-- subset of the environment, exposed by small, local typeclasses. For instance,
|
|
|
|
-- at time of writing, this can be used to implement 'HasServerConfigCtx', as a
|
|
|
|
-- first step towards breaking it down.
|
2023-05-17 17:02:09 +03:00
|
|
|
class (Monad m) => HasAppEnv m where
|
Clean `AppEnv` and `AppContext` passing, remove `RunT`, reduce `ServerConfigCtx` uses
## Description
This PR does several different things that happen to overlap; the most important being:
- it removes `RunT`: it was redundant in places where we already had `Handler`, and only used in one other place, `SchemaUpdate`, for which a local `SchemaUpdateT` is more than enough;
- it reduces the number of places where we create a `ServerConfigCtx`, since now `HasServerConfigCtx` can be implemented directly by `SchemaUpdateT` and `Handler` based on the full `AppContext`;
- it drastically reduces the number of arguments we pass around in the app init code, by introducing `HasAppEnv`;
- it simplifies `HandlerCtx` to reduce duplication
In doing so, this changes paves the way towards removing `ServerConfigCtx`, since there are only very few places where we construct it: we can now introduce smaller classes than `HasServerConfigCtx`, that expose only a relevant subset of fields, and implement them where we now implement `HasServerConfigCtx`.
This PR is loosely based on ideas in #8337, that are no longer applicable due to the changes introduced in #8159. A challenge of this PR was the postgres tests, which were running in `PGMetadataStorageAppT CacheBuild` :scream_cat:
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8392
GitOrigin-RevId: b90c1359066d20dbea329c87762ccdd1217b4d69
2023-03-21 13:44:21 +03:00
|
|
|
askAppEnv :: m AppEnv
|
|
|
|
|
|
|
|
instance (HasAppEnv m) => HasAppEnv (ReaderT r m) where
|
|
|
|
askAppEnv = lift askAppEnv
|
|
|
|
|
|
|
|
instance (HasAppEnv m) => HasAppEnv (ExceptT e m) where
|
|
|
|
askAppEnv = lift askAppEnv
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- init functions
|
|
|
|
|
2023-03-17 13:29:07 +03:00
|
|
|
initInvalidationKeys :: InvalidationKeys
|
|
|
|
initInvalidationKeys = InvalidationKeys
|
|
|
|
|
|
|
|
-- | Function to build the 'AppContext' (given the 'ServeOptions') for the first
|
|
|
|
-- time
|
|
|
|
buildRebuildableAppContext :: (L.Logger L.Hasura, HTTP.Manager) -> ServeOptions impl -> E.Environment -> ExceptT QErr IO (RebuildableAppContext impl)
|
|
|
|
buildRebuildableAppContext readerContext serveOptions env = do
|
|
|
|
result <- flip runReaderT readerContext $ Inc.build (buildAppContextRule) (serveOptions, env, initInvalidationKeys)
|
|
|
|
let !appContext = Inc.result result
|
|
|
|
let !rebuildableAppContext = RebuildableAppContext appContext initInvalidationKeys (Inc.rebuildRule result)
|
|
|
|
pure rebuildableAppContext
|
|
|
|
|
2023-03-30 19:31:50 +03:00
|
|
|
-- | Function to rebuild the 'AppContext' from a given 'RebuildableAppContext'
|
|
|
|
-- and a new 'ServeOptions'
|
|
|
|
rebuildRebuildableAppContext ::
|
|
|
|
(MonadIO m, MonadError QErr m) =>
|
|
|
|
(L.Logger L.Hasura, HTTP.Manager) ->
|
|
|
|
RebuildableAppContext impl ->
|
|
|
|
ServeOptions impl ->
|
|
|
|
E.Environment ->
|
|
|
|
m (RebuildableAppContext impl)
|
|
|
|
rebuildRebuildableAppContext readerCtx (RebuildableAppContext _ _ rule) serveOptions env = do
|
|
|
|
let newInvalidationKeys = InvalidationKeys
|
|
|
|
result <-
|
2023-05-24 16:51:56 +03:00
|
|
|
liftEitherM
|
|
|
|
$ liftIO
|
|
|
|
$ runExceptT
|
|
|
|
$ flip runReaderT readerCtx
|
|
|
|
$ Inc.build rule (serveOptions, env, newInvalidationKeys)
|
2023-03-30 19:31:50 +03:00
|
|
|
let appContext = Inc.result result
|
|
|
|
!newCtx = RebuildableAppContext appContext newInvalidationKeys (Inc.rebuildRule result)
|
|
|
|
pure newCtx
|
|
|
|
|
2023-03-17 13:29:07 +03:00
|
|
|
buildAppContextRule ::
|
|
|
|
forall arr m impl.
|
|
|
|
( ArrowChoice arr,
|
|
|
|
Inc.ArrowCache m arr,
|
|
|
|
MonadBaseControl IO m,
|
|
|
|
MonadIO m,
|
|
|
|
MonadError QErr m,
|
|
|
|
MonadReader (L.Logger L.Hasura, HTTP.Manager) m
|
|
|
|
) =>
|
|
|
|
(ServeOptions impl, E.Environment, InvalidationKeys) `arr` AppContext
|
|
|
|
buildAppContextRule = proc (ServeOptions {..}, env, _keys) -> do
|
|
|
|
authMode <- buildAuthMode -< (soAdminSecret, soAuthHook, soJwtSecret, soUnAuthRole)
|
|
|
|
sqlGenCtx <- buildSqlGenCtx -< (soExperimentalFeatures, soStringifyNum, soDangerousBooleanCollapse)
|
|
|
|
responseInternalErrorsConfig <- buildResponseInternalErrorsConfig -< (soAdminInternalErrors, soDevMode)
|
|
|
|
eventEngineCtx <- buildEventEngineCtx -< (soEventsHttpPoolSize, soEventsFetchInterval, soEventsFetchBatchSize)
|
|
|
|
returnA
|
|
|
|
-<
|
|
|
|
AppContext
|
|
|
|
{ acAuthMode = authMode,
|
|
|
|
acSQLGenCtx = sqlGenCtx,
|
|
|
|
acEnabledAPIs = soEnabledAPIs,
|
|
|
|
acEnableAllowlist = soEnableAllowList,
|
|
|
|
acResponseInternalErrorsConfig = responseInternalErrorsConfig,
|
|
|
|
acEnvironment = env,
|
|
|
|
acRemoteSchemaPermsCtx = soEnableRemoteSchemaPermissions,
|
|
|
|
acFunctionPermsCtx = soInferFunctionPermissions,
|
|
|
|
acExperimentalFeatures = soExperimentalFeatures,
|
|
|
|
acDefaultNamingConvention = soDefaultNamingConvention,
|
|
|
|
acMetadataDefaults = soMetadataDefaults,
|
|
|
|
acLiveQueryOptions = soLiveQueryOpts,
|
|
|
|
acStreamQueryOptions = soStreamingQueryOpts,
|
|
|
|
acCorsPolicy = Cors.mkDefaultCorsPolicy soCorsConfig,
|
|
|
|
acConsoleStatus = soConsoleStatus,
|
|
|
|
acEnableTelemetry = soEnableTelemetry,
|
|
|
|
acEventEngineCtx = eventEngineCtx,
|
|
|
|
acAsyncActionsFetchInterval = soAsyncActionsFetchInterval,
|
|
|
|
acApolloFederationStatus = soApolloFederationStatus
|
|
|
|
}
|
|
|
|
where
|
|
|
|
buildSqlGenCtx = Inc.cache proc (experimentalFeatures, stringifyNum, dangerousBooleanCollapse) -> do
|
|
|
|
let sqlGenCtx = initSQLGenCtx experimentalFeatures stringifyNum dangerousBooleanCollapse
|
|
|
|
returnA -< sqlGenCtx
|
|
|
|
|
|
|
|
buildEventEngineCtx = Inc.cache proc (httpPoolSize, fetchInterval, fetchBatchSize) -> do
|
|
|
|
eventEngineCtx <- bindA -< initEventEngineCtx httpPoolSize fetchInterval fetchBatchSize
|
|
|
|
returnA -< eventEngineCtx
|
|
|
|
|
|
|
|
buildAuthMode :: (Set.HashSet AdminSecretHash, Maybe AuthHook, [JWTConfig], Maybe RoleName) `arr` AuthMode
|
|
|
|
buildAuthMode = Inc.cache proc (adminSecretHashSet, webHook, jwtSecrets, unAuthRole) -> do
|
|
|
|
authMode <-
|
|
|
|
bindA
|
|
|
|
-< do
|
|
|
|
(logger, httpManager) <- ask
|
|
|
|
authModeRes <-
|
2023-05-24 16:51:56 +03:00
|
|
|
runExceptT
|
|
|
|
$ setupAuthMode
|
2023-03-17 13:29:07 +03:00
|
|
|
adminSecretHashSet
|
|
|
|
webHook
|
|
|
|
jwtSecrets
|
|
|
|
unAuthRole
|
|
|
|
logger
|
|
|
|
httpManager
|
|
|
|
onLeft authModeRes throw500
|
|
|
|
returnA -< authMode
|
|
|
|
|
|
|
|
buildResponseInternalErrorsConfig :: (AdminInternalErrorsStatus, DevModeStatus) `arr` ResponseInternalErrorsConfig
|
|
|
|
buildResponseInternalErrorsConfig = Inc.cache proc (adminInternalErrors, devMode) -> do
|
|
|
|
let responseInternalErrorsConfig =
|
|
|
|
if
|
2023-05-24 16:51:56 +03:00
|
|
|
| isDevModeEnabled devMode -> InternalErrorsAllRequests
|
|
|
|
| isAdminInternalErrorsEnabled adminInternalErrors -> InternalErrorsAdminOnly
|
|
|
|
| otherwise -> InternalErrorsDisabled
|
2023-03-17 13:29:07 +03:00
|
|
|
returnA -< responseInternalErrorsConfig
|
|
|
|
|
Remove `ServerConfigCtx`.
### Description
This PR removes `ServerConfigCtx` and `HasServerConfigCtx`. Instead, it favours different approaches:
- when the code was only using one field, it passes that field explicitly (usually `SQLGenCtx` or `CheckFeatureFlag`)
- when the code was using several fields, but in only one function, it inlines
- for the cache build, it introduces `CacheStaticConfig` and `CacheDynamicConfig`, which are subsets of `AppEnv` and `AppContext` respectively
The main goal of this is to help with the modularization of the engine: as `ServerConfigCtx` had fields whose types were imported from several unrelated parts of the engine, using it tied together parts of the engine that should not be aware of one another (such as tying together `Hasura.LogicalModel` and `Hasura.GraphQL.Schema`).
The bulk of this PR is a change to the cache build, as a follow up to #8509: instead of giving the entire `ServerConfigCtx` as a incremental rule argument, we only give the new `CacheDynamicConfig` struct, which has fewer fields. The other required fields, that were coming from the `AppEnv`, are now given via the `HasCacheStaticConfig` constraint, which is a "subset" of `HasAppEnv`.
(Some further work could include moving `StringifyNumbers` out of `GraphQL.Schema.Options`, given how it is used all across the codebase, including in `RQL.DML`.)
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8513
GitOrigin-RevId: 818cbcd71494e3cd946b06adbb02ca328a8a298e
2023-04-04 18:59:58 +03:00
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- subsets
|
|
|
|
|
2023-03-17 13:29:07 +03:00
|
|
|
initSQLGenCtx :: HashSet ExperimentalFeature -> Options.StringifyNumbers -> Options.DangerouslyCollapseBooleans -> SQLGenCtx
|
|
|
|
initSQLGenCtx experimentalFeatures stringifyNum dangerousBooleanCollapse =
|
|
|
|
let optimizePermissionFilters
|
|
|
|
| EFOptimizePermissionFilters `elem` experimentalFeatures = Options.OptimizePermissionFilters
|
|
|
|
| otherwise = Options.Don'tOptimizePermissionFilters
|
|
|
|
|
|
|
|
bigqueryStringNumericInput
|
|
|
|
| EFBigQueryStringNumericInput `elem` experimentalFeatures = Options.EnableBigQueryStringNumericInput
|
|
|
|
| otherwise = Options.DisableBigQueryStringNumericInput
|
|
|
|
in SQLGenCtx stringifyNum dangerousBooleanCollapse optimizePermissionFilters bigqueryStringNumericInput
|
Remove `HasServerConfigCtx` from the schema cache build.
## Description
This PR is a incremental step towards achieving the goal of #8344. It is a less ambitious version of #8484.
This PR removes all references to `HasServerConfigCtx` from the cache build and removes `ServerConfigCtx` from `CacheBuildParams`, making `ServerConfigCtx` an argument being passed around manually instead. This has several benefits: by making it an arrow argument, we now properly integrate the fields that change over time in the dependency framework, as they should be, and we can clean up some of the top-level app code.
## Implementation
In practice, this PR introduces a `HasServerConfigCtx` instance for `CacheRWT`, the monad we use to build the cache, so we can retrieve the `ServerConfigCtx` in the implementation of `CacheRWM`. This contributes to reducing the amount of `HasServerConfigCtx` in the code: we can remove `SchemaUpdateT` altogether, and we can remove the `HasServerConfigCtx` instance of `Handler`. This makes `HasServerConfigCtx` almost **an implementation detail of the Metadata API**.
This first step is enough to achieve the goal of #8344: we can now build the schema cache in the app monad, since we no longer rely on `HasServerConfigCtx` to build it.
## Drawbacks
This PR does not attempt to remove the use of `ServerConfigCtx` itself in the schema cache build: doing so would make this PR much much bigger. Ideally, to avoid having all the static fields given as arrow-ish arguments to the cache, we could depend on `HasAppEnv` in the cache build, and use `AppContext` as an arrow argument. But making the cache build depend on the full `AppEnv` and `AppContext` creates a lot of circular imports; and since removing `ServerConfigCtx` itself isn't required to achieve #8344, this PR keeps it wholesale and defers cleaning it to a future PR.
A negative consequence of this is that we need an `Eq` instance on `ServerConfigCtx`, and that instance is inelegant.
## Future work
There are several further steps we can take in parallel after this is merged. First, again, we can make a new version of #8344, removing `CacheBuild`, FINALLY. As for `ServerConfigCtx`, we can split it / rename it to make ad-hoc structures. If it turns out that `ServerConfigCtx` is only ever used for the schema cache build, we could split it between `CacheBuildEnv` and `CacheBuildContext`, which will be subsets of `AppEnv` and `AppContext`, avoiding import loops.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8509
GitOrigin-RevId: 01b37cc3fd3490d6b117701e22fc4ac88b62b6b5
2023-03-27 20:42:37 +03:00
|
|
|
|
Remove `ServerConfigCtx`.
### Description
This PR removes `ServerConfigCtx` and `HasServerConfigCtx`. Instead, it favours different approaches:
- when the code was only using one field, it passes that field explicitly (usually `SQLGenCtx` or `CheckFeatureFlag`)
- when the code was using several fields, but in only one function, it inlines
- for the cache build, it introduces `CacheStaticConfig` and `CacheDynamicConfig`, which are subsets of `AppEnv` and `AppContext` respectively
The main goal of this is to help with the modularization of the engine: as `ServerConfigCtx` had fields whose types were imported from several unrelated parts of the engine, using it tied together parts of the engine that should not be aware of one another (such as tying together `Hasura.LogicalModel` and `Hasura.GraphQL.Schema`).
The bulk of this PR is a change to the cache build, as a follow up to #8509: instead of giving the entire `ServerConfigCtx` as a incremental rule argument, we only give the new `CacheDynamicConfig` struct, which has fewer fields. The other required fields, that were coming from the `AppEnv`, are now given via the `HasCacheStaticConfig` constraint, which is a "subset" of `HasAppEnv`.
(Some further work could include moving `StringifyNumbers` out of `GraphQL.Schema.Options`, given how it is used all across the codebase, including in `RQL.DML`.)
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8513
GitOrigin-RevId: 818cbcd71494e3cd946b06adbb02ca328a8a298e
2023-04-04 18:59:58 +03:00
|
|
|
buildCacheStaticConfig :: AppEnv -> CacheStaticConfig
|
|
|
|
buildCacheStaticConfig AppEnv {..} =
|
|
|
|
CacheStaticConfig
|
|
|
|
{ _cscMaintenanceMode = appEnvEnableMaintenanceMode,
|
|
|
|
_cscEventingMode = appEnvEventingMode,
|
2023-04-27 17:30:23 +03:00
|
|
|
_cscReadOnlyMode = appEnvEnableReadOnlyMode,
|
2023-05-04 15:43:59 +03:00
|
|
|
_cscAreNativeQueriesEnabled = False,
|
|
|
|
_cscAreStoredProceduresEnabled = False
|
Remove `ServerConfigCtx`.
### Description
This PR removes `ServerConfigCtx` and `HasServerConfigCtx`. Instead, it favours different approaches:
- when the code was only using one field, it passes that field explicitly (usually `SQLGenCtx` or `CheckFeatureFlag`)
- when the code was using several fields, but in only one function, it inlines
- for the cache build, it introduces `CacheStaticConfig` and `CacheDynamicConfig`, which are subsets of `AppEnv` and `AppContext` respectively
The main goal of this is to help with the modularization of the engine: as `ServerConfigCtx` had fields whose types were imported from several unrelated parts of the engine, using it tied together parts of the engine that should not be aware of one another (such as tying together `Hasura.LogicalModel` and `Hasura.GraphQL.Schema`).
The bulk of this PR is a change to the cache build, as a follow up to #8509: instead of giving the entire `ServerConfigCtx` as a incremental rule argument, we only give the new `CacheDynamicConfig` struct, which has fewer fields. The other required fields, that were coming from the `AppEnv`, are now given via the `HasCacheStaticConfig` constraint, which is a "subset" of `HasAppEnv`.
(Some further work could include moving `StringifyNumbers` out of `GraphQL.Schema.Options`, given how it is used all across the codebase, including in `RQL.DML`.)
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8513
GitOrigin-RevId: 818cbcd71494e3cd946b06adbb02ca328a8a298e
2023-04-04 18:59:58 +03:00
|
|
|
}
|
|
|
|
|
2023-04-27 17:30:23 +03:00
|
|
|
buildCacheDynamicConfig :: AppContext -> CacheDynamicConfig
|
|
|
|
buildCacheDynamicConfig AppContext {..} = do
|
|
|
|
CacheDynamicConfig
|
|
|
|
{ _cdcFunctionPermsCtx = acFunctionPermsCtx,
|
|
|
|
_cdcRemoteSchemaPermsCtx = acRemoteSchemaPermsCtx,
|
|
|
|
_cdcSQLGenCtx = acSQLGenCtx,
|
|
|
|
_cdcExperimentalFeatures = acExperimentalFeatures,
|
|
|
|
_cdcDefaultNamingConvention = acDefaultNamingConvention,
|
|
|
|
_cdcMetadataDefaults = acMetadataDefaults,
|
|
|
|
_cdcApolloFederationStatus = acApolloFederationStatus
|
|
|
|
}
|