Reapply "Reapply "subscriptions: Unhide OpenDd Metadata and lift from unstability" " (#1256) (#1266)

<!-- The PR description should answer 2 important questions: -->

### What

<!-- What is this PR trying to accomplish (and why, if it's not
obvious)? -->

<!-- Consider: do we need to add a changelog entry? -->

<!-- Does this PR introduce new validation that might break old builds?
-->

<!-- Consider: do we need to put new checks behind a flag? -->

### How

<!-- How is it trying to accomplish it (what are the implementation
steps)? -->

V3_GIT_ORIGIN_REV_ID: 894ba81666bb441e71b8e204b89e5732ac4f1c83
This commit is contained in:
Rakesh Emmadi 2024-10-23 20:47:56 +05:30 committed by hasura-bot
parent cff4920552
commit be748992f4
16 changed files with 120 additions and 45 deletions

View File

@ -19,7 +19,6 @@
pub enum UnstableFeature {
EnableOrderByExpressions,
EnableNdcV02Support,
EnableSubscriptions,
EnableJsonApi,
EnableAggregationPredicates,
}
@ -37,9 +36,6 @@ pub fn resolve_unstable_features(
UnstableFeature::EnableNdcV02Support => {
features.enable_ndc_v02_support = true;
}
UnstableFeature::EnableSubscriptions => {
features.enable_subscriptions = true;
}
UnstableFeature::EnableJsonApi => {
features.enable_jsonapi = true;
}

View File

@ -480,7 +480,6 @@ pub fn test_execute_explain(
unstable_features: metadata_resolve::configuration::UnstableFeatures {
enable_order_by_expressions: false,
enable_ndc_v02_support: true,
enable_subscriptions: false,
enable_jsonapi: false,
..Default::default()
},
@ -542,7 +541,6 @@ pub(crate) fn test_metadata_resolve_configuration() -> metadata_resolve::configu
unstable_features: metadata_resolve::configuration::UnstableFeatures {
enable_order_by_expressions: false,
enable_ndc_v02_support: true,
enable_subscriptions: true,
enable_jsonapi: false,
..Default::default()
},

View File

@ -59,12 +59,7 @@ pub(crate) async fn start_websocket_server() -> TestServer {
let metadata_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(METADATA_PATH);
let raw_metadata = std::fs::read_to_string(metadata_path).unwrap();
let metadata = open_dds::Metadata::from_json_str(&raw_metadata).unwrap();
let metadata_resolve_configuration = metadata_resolve::configuration::Configuration {
unstable_features: metadata_resolve::configuration::UnstableFeatures {
enable_subscriptions: true,
..Default::default()
},
};
let metadata_resolve_configuration = metadata_resolve::configuration::Configuration::default();
let (resolved_metadata, _warnings) =
metadata_resolve::resolve(metadata, &metadata_resolve_configuration).unwrap();

View File

@ -207,7 +207,6 @@ fn get_metadata_resolve_configuration() -> metadata_resolve::configuration::Conf
let unstable_features = metadata_resolve::configuration::UnstableFeatures {
enable_order_by_expressions: false,
enable_ndc_v02_support: false,
enable_subscriptions: true,
enable_jsonapi: true,
enable_aggregation_predicates: false,
};

View File

@ -262,7 +262,6 @@ fn fallback_graphql_config() -> &'static graphql_config::GraphqlConfig {
mutation: graphql_config::MutationGraphqlConfig {
root_operation_type_name: GraphQlTypeName::from("Mutation"),
},
// TODO: Subscriptions are still unsupported. No need to consider them for now.
subscription: None,
apollo_federation: None,
})

View File

@ -275,7 +275,6 @@ pub fn resolve(
&order_by_expressions,
&graphql_types,
&graphql_config,
configuration,
)?;
all_issues.extend(issues);

View File

@ -11,7 +11,6 @@ use super::types::{
SelectAggregateGraphQlDefinition, SelectManyGraphQlDefinition, SelectUniqueGraphQlDefinition,
SubscriptionGraphQlDefinition, UniqueIdentifierField,
};
use crate::configuration::Configuration;
use crate::helpers::types::{mk_name, store_new_graphql_type};
use crate::stages::order_by_expressions::OrderByExpressions;
use crate::stages::{data_connector_scalar_types, graphql_config, models, object_types};
@ -36,7 +35,6 @@ pub(crate) fn resolve_model_graphql_api(
aggregate_expression_name: &Option<Qualified<AggregateExpressionName>>,
order_by_expressions: &OrderByExpressions,
graphql_config: &graphql_config::GraphqlConfig,
configuration: &Configuration,
issues: &mut Vec<Warning>,
) -> Result<ModelGraphQlApi, Error> {
let model_name = &model.name;
@ -94,7 +92,7 @@ pub(crate) fn resolve_model_graphql_api(
let subscription = select_unique
.subscription
.as_ref()
.map(|s| resolve_subscription_graphql_api(s, configuration))
.map(resolve_subscription_graphql_api)
.transpose()?;
graphql_api
.select_uniques
@ -171,7 +169,7 @@ pub(crate) fn resolve_model_graphql_api(
let subscription = gql_definition
.subscription
.as_ref()
.map(|s| resolve_subscription_graphql_api(s, configuration))
.map(resolve_subscription_graphql_api)
.transpose()?;
mk_name(gql_definition.query_root_field.as_str()).map(|f: ast::Name| {
let select_many_description = if gql_definition.description.is_some() {
@ -242,7 +240,7 @@ pub(crate) fn resolve_model_graphql_api(
let subscription = graphql_aggregate
.subscription
.as_ref()
.map(|s| resolve_subscription_graphql_api(s, configuration))
.map(resolve_subscription_graphql_api)
.transpose()?;
Some(SelectAggregateGraphQlDefinition {
@ -336,12 +334,8 @@ fn is_model_used_in_any_aggregate_relationship(
fn resolve_subscription_graphql_api(
subscription: &open_dds::models::SubscriptionGraphQlDefinition,
configuration: &Configuration,
) -> Result<SubscriptionGraphQlDefinition, Error> {
// Subscriptions are currently unstable.
if !configuration.unstable_features.enable_subscriptions {
return Err(Error::UnstableFeatureSubscriptions);
}
let open_dds::models::SubscriptionGraphQlDefinition {
root_field,
description,

View File

@ -9,7 +9,6 @@ use std::collections::{BTreeMap, BTreeSet};
use lang_graphql::ast::common as ast;
use open_dds::{data_connector::DataConnectorName, models::ModelName, types::CustomTypeName};
use crate::configuration::Configuration;
use crate::stages::{
boolean_expressions, data_connector_scalar_types, graphql_config, models,
object_boolean_expressions, object_relationships,
@ -45,7 +44,6 @@ pub fn resolve(
order_by_expressions: &order_by_expressions::OrderByExpressions,
existing_graphql_types: &BTreeSet<ast::TypeName>,
graphql_config: &graphql_config::GraphqlConfig,
configuration: &Configuration,
) -> Result<ModelsWithGraphqlOutput, Error> {
let mut output = ModelsWithGraphqlOutput {
models_with_graphql: IndexMap::new(),
@ -99,7 +97,6 @@ pub fn resolve(
&model.aggregate_expression,
order_by_expressions,
graphql_config,
configuration,
&mut output.issues,
)?,
None => types::ModelGraphQlApi::default(),

View File

@ -16,7 +16,6 @@ pub struct Configuration {
pub struct UnstableFeatures {
pub enable_order_by_expressions: bool,
pub enable_ndc_v02_support: bool,
pub enable_subscriptions: bool,
pub enable_jsonapi: bool,
pub enable_aggregation_predicates: bool,
}

View File

@ -345,8 +345,6 @@ pub enum Error {
CompatibilityError {
warnings_as_errors: SeparatedBy<crate::Warning>,
},
#[error("Subscriptions are currently unstable. Please add 'subscriptions' to unstable features to enable them.")]
UnstableFeatureSubscriptions,
}
pub trait ShouldBeAnError {

View File

@ -83,7 +83,6 @@ fn read_test_configuration(
let unstable_features = configuration::UnstableFeatures {
enable_order_by_expressions: false,
enable_ndc_v02_support: false,
enable_subscriptions: false,
enable_jsonapi: false,
enable_aggregation_predicates: true,
};

View File

@ -1948,6 +1948,16 @@
"mutation": {
"$ref": "#/definitions/MutationGraphqlConfig"
},
"subscription": {
"anyOf": [
{
"$ref": "#/definitions/SubscriptionGraphqlConfig"
},
{
"type": "null"
}
]
},
"apolloFederation": {
"anyOf": [
{
@ -2322,6 +2332,17 @@
"type": "null"
}
]
},
"subscription": {
"description": "Enable subscription on this aggregate root field.",
"anyOf": [
{
"$ref": "#/definitions/SubscriptionGraphQlDefinition"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
@ -5245,6 +5266,17 @@
"type": "null"
}
]
},
"subscription": {
"description": "Enable subscription on this select many root field.",
"anyOf": [
{
"$ref": "#/definitions/SubscriptionGraphQlDefinition"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
@ -5273,6 +5305,11 @@
"items": {
"$ref": "#/definitions/ArgumentPreset"
}
},
"allowSubscriptions": {
"description": "Whether the role is allowed to subscribe to the root fields of this model.",
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
@ -5319,6 +5356,82 @@
"type": "null"
}
]
},
"subscription": {
"description": "Enable subscription on this select unique root field.",
"anyOf": [
{
"$ref": "#/definitions/SubscriptionGraphQlDefinition"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"SubscriptionGraphQlDefinition": {
"$id": "https://hasura.io/jsonschemas/metadata/SubscriptionGraphQlDefinition",
"title": "SubscriptionGraphQlDefinition",
"description": "The definition of the GraphQL API for enabling subscription on query root fields.",
"type": "object",
"required": [
"rootField"
],
"properties": {
"rootField": {
"description": "The name of the subscription root field.",
"allOf": [
{
"$ref": "#/definitions/GraphQlFieldName"
}
]
},
"description": {
"description": "The description of the subscription graphql definition. Gets added to the description of the subscription root field in the graphql schema.",
"type": [
"string",
"null"
]
},
"deprecated": {
"description": "Whether this subscription root field is deprecated. If set, the deprecation status is added to the subscription root field's graphql schema.",
"anyOf": [
{
"$ref": "#/definitions/Deprecated"
},
{
"type": "null"
}
]
},
"pollingIntervalMs": {
"description": "Polling interval in milliseconds for the subscription.",
"default": 1000,
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
"SubscriptionGraphqlConfig": {
"$id": "https://hasura.io/jsonschemas/metadata/SubscriptionGraphqlConfig",
"title": "SubscriptionGraphqlConfig",
"description": "Configuration for the GraphQL schema of Hasura features for subscriptions.",
"type": "object",
"required": [
"rootOperationTypeName"
],
"properties": {
"rootOperationTypeName": {
"description": "The name of the root operation type name for subscriptions. Usually `subscription`.",
"allOf": [
{
"$ref": "#/definitions/GraphQlTypeName"
}
]
}
},
"additionalProperties": false

View File

@ -30,8 +30,6 @@ pub enum GraphqlConfig {
pub struct GraphqlConfigV1 {
pub query: QueryGraphqlConfig,
pub mutation: MutationGraphqlConfig,
#[opendd(hidden = true)]
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription: Option<SubscriptionGraphqlConfig>,
pub apollo_federation: Option<GraphqlApolloFederationConfig>,
}

View File

@ -385,7 +385,6 @@ pub struct SelectUniqueGraphQlDefinition {
/// If set, the deprecation status is added to the select unique root field's graphql schema.
pub deprecated: Option<Deprecated>,
/// Enable subscription on this select unique root field.
#[opendd(hidden = true)]
pub subscription: Option<SubscriptionGraphQlDefinition>,
}
@ -403,11 +402,10 @@ pub struct SelectManyGraphQlDefinition {
/// If set, the deprecation status is added to the select many root field's graphql schema.
pub deprecated: Option<Deprecated>,
/// Enable subscription on this select many root field.
#[opendd(hidden = true)]
pub subscription: Option<SubscriptionGraphQlDefinition>,
}
/// The definition of the GraphQL API for enabling subscription on select_many or select_uniques root fields.
/// The definition of the GraphQL API for enabling subscription on query root fields.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, opendds_derive::OpenDd)]
#[serde(rename_all = "camelCase")]
#[opendd(json_schema(title = "SubscriptionGraphQlDefinition"))]
@ -502,6 +500,5 @@ pub struct ModelAggregateGraphQlDefinition {
/// If set, the deprecation status is added to the aggregate root field's graphql schema.
pub deprecated: Option<Deprecated>,
/// Enable subscription on this aggregate root field.
#[opendd(hidden = true)]
pub subscription: Option<SubscriptionGraphQlDefinition>,
}

View File

@ -342,12 +342,8 @@ pub struct SelectPermission {
/// Preset values for arguments for this role
#[opendd(default, json_schema(default_exp = "serde_json::json!([])"))]
pub argument_presets: Vec<ArgumentPreset>,
/// Whether to allow subscriptions for this role.
#[opendd(
hidden = true,
default,
json_schema(default_exp = "serde_json::json!(false)")
)]
/// Whether the role is allowed to subscribe to the root fields of this model.
#[opendd(default, json_schema(default_exp = "serde_json::json!(false)"))]
pub allow_subscriptions: bool,
}

View File

@ -85,7 +85,6 @@ watch: start-docker-test-deps start-docker-run-deps
--otlp-endpoint http://localhost:4317 \
--authn-config-path static/auth/auth_config.json \
--metadata-path static/sample-schema.json \
--unstable-feature enable-subscriptions \
--unstable-feature enable-json-api \
--expose-internal-errors'
@ -175,6 +174,5 @@ run METADATA_PATH="static/sample-schema.json": start-docker-test-deps start-dock
--otlp-endpoint http://localhost:4317 \
--authn-config-path static/auth/auth_config.json \
--metadata-path {{ METADATA_PATH }} \
--unstable-feature enable-subscriptions \
--unstable-feature enable-json-api \
--expose-internal-errors