Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

indexer-alt: generalize GraphQLConfig #20460

Merged
merged 3 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ members = [
"crates/sui-data-ingestion",
"crates/sui-data-ingestion-core",
"crates/sui-deepbook-indexer",
"crates/sui-default-config",
"crates/sui-e2e-tests",
"crates/sui-enum-compat-util",
"crates/sui-faucet",
Expand All @@ -109,7 +110,6 @@ members = [
"crates/sui-framework-snapshot",
"crates/sui-framework-tests",
"crates/sui-genesis-builder",
"crates/sui-graphql-config",
"crates/sui-graphql-e2e-tests",
"crates/sui-graphql-rpc",
"crates/sui-graphql-rpc-client",
Expand Down Expand Up @@ -631,6 +631,7 @@ sui-core = { path = "crates/sui-core" }
sui-cost = { path = "crates/sui-cost" }
sui-data-ingestion = { path = "crates/sui-data-ingestion" }
sui-data-ingestion-core = { path = "crates/sui-data-ingestion-core" }
sui-default-config = { path = "crates/sui-default-config" }
sui-e2e-tests = { path = "crates/sui-e2e-tests" }
sui-enum-compat-util = { path = "crates/sui-enum-compat-util" }
sui-faucet = { path = "crates/sui-faucet" }
Expand All @@ -639,7 +640,6 @@ sui-field-count-derive = { path = "crates/sui-field-count-derive" }
sui-framework = { path = "crates/sui-framework" }
sui-framework-snapshot = { path = "crates/sui-framework-snapshot" }
sui-framework-tests = { path = "crates/sui-framework-tests" }
sui-graphql-config = { path = "crates/sui-graphql-config" }
sui-graphql-rpc = { path = "crates/sui-graphql-rpc" }
sui-graphql-rpc-client = { path = "crates/sui-graphql-rpc-client" }
sui-graphql-rpc-headers = { path = "crates/sui-graphql-rpc-headers" }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "sui-graphql-config"
name = "sui-default-config"
version.workspace = true
authors = ["Mysten Labs <[email protected]"]
license = "Apache-2.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use std::collections::BTreeSet;

use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::{
parse_macro_input, Attribute, Data, DataStruct, DeriveInput, Fields, FieldsNamed, Ident, Meta,
NestedMeta,
parse_macro_input, Attribute, Data, DataStruct, DeriveInput, Fields, FieldsNamed, Meta,
MetaList, MetaNameValue, NestedMeta,
};

/// Attribute macro to be applied to config-based structs. It ensures that the struct derives serde
Expand All @@ -17,7 +15,7 @@ use syn::{
/// the config struct.
#[allow(non_snake_case)]
#[proc_macro_attribute]
pub fn GraphQLConfig(_attr: TokenStream, input: TokenStream) -> TokenStream {
pub fn DefaultConfig(_attr: TokenStream, input: TokenStream) -> TokenStream {
let DeriveInput {
attrs,
vis,
Expand All @@ -32,20 +30,17 @@ pub fn GraphQLConfig(_attr: TokenStream, input: TokenStream) -> TokenStream {
semi_token,
}) = data
else {
panic!("GraphQL configs must be structs.");
panic!("Default configs must be structs.");
};

let Fields::Named(FieldsNamed {
brace_token: _,
named,
}) = fields
else {
panic!("GraphQL configs must have named fields.");
panic!("Default configs must have named fields.");
};

// Figure out which derives need to be added to meet the criteria of a config struct.
let core_derives = core_derives(&attrs);

// Extract field names once to avoid having to check for their existence multiple times.
let fields_with_names: Vec<_> = named
.iter()
Expand Down Expand Up @@ -73,14 +68,40 @@ pub fn GraphQLConfig(_attr: TokenStream, input: TokenStream) -> TokenStream {
quote! {
#[doc(hidden)] #cfg
fn #fn_name() -> #ty {
Self::default().#name
<Self as std::default::Default>::default().#name
}
}
});

// Check if there's already a serde rename_all attribute
let has_rename_all = attrs.iter().any(|attr| {
if !attr.path.is_ident("serde") {
return false;
};

let Ok(Meta::List(MetaList { nested, .. })) = attr.parse_meta() else {
return false;
};

nested.iter().any(|nested| {
if let NestedMeta::Meta(Meta::NameValue(MetaNameValue { path, .. })) = nested {
path.is_ident("rename_all")
} else {
false
}
})
});

// Only include the default rename_all if none exists
let rename_all = if !has_rename_all {
quote! { #[serde(rename_all = "kebab-case")] }
} else {
quote! {}
};

TokenStream::from(quote! {
#[derive(#(#core_derives),*)]
#[serde(rename_all = "kebab-case")]
#[derive(serde::Serialize, serde::Deserialize)]
#rename_all
#(#attrs)* #vis #struct_token #ident #generics {
#(#fields),*
} #semi_token
Expand All @@ -91,49 +112,6 @@ pub fn GraphQLConfig(_attr: TokenStream, input: TokenStream) -> TokenStream {
})
}

/// Return a set of derives that should be added to the struct to make sure it derives all the
/// things we expect from a config, namely `Serialize`, `Deserialize`, and `Debug`.
///
/// We cannot add core derives unconditionally, because they will conflict with existing ones.
fn core_derives(attrs: &[Attribute]) -> BTreeSet<Ident> {
let mut derives = BTreeSet::from_iter([
format_ident!("Serialize"),
format_ident!("Deserialize"),
format_ident!("Debug"),
format_ident!("Clone"),
format_ident!("Eq"),
format_ident!("PartialEq"),
]);

for attr in attrs {
let Ok(Meta::List(list)) = attr.parse_meta() else {
continue;
};

let Some(ident) = list.path.get_ident() else {
continue;
};

if ident != "derive" {
continue;
}

for nested in list.nested {
let NestedMeta::Meta(Meta::Path(path)) = nested else {
continue;
};

let Some(ident) = path.get_ident() else {
continue;
};

derives.remove(ident);
}
}

derives
}

/// Find the attribute that corresponds to a `#[cfg(...)]` annotation, if it exists.
fn extract_cfg(attrs: &[Attribute]) -> Option<&Attribute> {
attrs.iter().find(|attr| {
Expand Down
2 changes: 1 addition & 1 deletion crates/sui-graphql-rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ uuid.workspace = true
im.workspace = true
downcast = "0.11.0"

sui-graphql-config.workspace = true
sui-default-config.workspace = true
sui-graphql-rpc-headers.workspace = true
sui-graphql-rpc-client.workspace = true

Expand Down
44 changes: 23 additions & 21 deletions crates/sui-graphql-rpc/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use move_core_types::ident_str;
use move_core_types::identifier::IdentStr;
use serde::{Deserialize, Serialize};
use std::{collections::BTreeSet, fmt::Display, time::Duration};
use sui_graphql_config::GraphQLConfig;
use sui_default_config::DefaultConfig;
use sui_json_rpc::name_service::NameServiceConfig;
use sui_types::base_types::{ObjectID, SuiAddress};

Expand All @@ -28,8 +28,8 @@ const MOVE_REGISTRY_TABLE_ID: &str =
const DEFAULT_PAGE_LIMIT: u16 = 50;

/// The combination of all configurations for the GraphQL service.
#[GraphQLConfig]
#[derive(Default)]
#[DefaultConfig]
#[derive(Clone, Default, Debug)]
pub struct ServerConfig {
pub service: ServiceConfig,
pub connection: ConnectionConfig,
Expand All @@ -41,8 +41,8 @@ pub struct ServerConfig {
/// Configuration for connections for the RPC, passed in as command-line arguments. This configures
/// specific connections between this service and other services, and might differ from instance to
/// instance of the GraphQL service.
#[GraphQLConfig]
#[derive(clap::Args, Clone, Eq, PartialEq)]
#[DefaultConfig]
#[derive(clap::Args, Clone, Eq, PartialEq, Debug)]
pub struct ConnectionConfig {
/// Port to bind the server to
#[clap(short, long, default_value_t = ConnectionConfig::default().port)]
Expand Down Expand Up @@ -71,8 +71,8 @@ pub struct ConnectionConfig {
/// Configuration on features supported by the GraphQL service, passed in a TOML-based file. These
/// configurations are shared across fleets of the service, i.e. all testnet services will have the
/// same `ServiceConfig`.
#[GraphQLConfig]
#[derive(Default)]
#[DefaultConfig]
#[derive(Clone, Default, Eq, PartialEq, Debug)]
pub struct ServiceConfig {
pub limits: Limits,
pub disabled_features: BTreeSet<FunctionalGroup>,
Expand All @@ -83,7 +83,8 @@ pub struct ServiceConfig {
pub move_registry: MoveRegistryConfig,
}

#[GraphQLConfig]
#[DefaultConfig]
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct Limits {
/// Maximum depth of nodes in the requests.
pub max_query_depth: u32,
Expand Down Expand Up @@ -127,16 +128,16 @@ pub struct Limits {
pub max_scan_limit: u32,
}

#[GraphQLConfig]
#[derive(Copy)]
#[DefaultConfig]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct BackgroundTasksConfig {
/// How often the watermark task checks the indexer database to update the checkpoint and epoch
/// watermarks.
pub watermark_update_ms: u64,
}

#[GraphQLConfig]
#[derive(Clone)]
#[DefaultConfig]
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct MoveRegistryConfig {
pub(crate) external_api_url: Option<String>,
pub(crate) resolution_type: ResolutionType,
Expand Down Expand Up @@ -185,24 +186,25 @@ impl Version {
}
}

#[GraphQLConfig]
#[derive(clap::Args)]
#[DefaultConfig]
#[derive(clap::Args, Clone, Debug)]
pub struct Ide {
/// The title to display at the top of the web-based GraphiQL IDE.
#[clap(short, long, default_value_t = Ide::default().ide_title)]
pub ide_title: String,
}

#[GraphQLConfig]
#[derive(Default)]
#[DefaultConfig]
#[derive(Clone, Default, Eq, PartialEq, Debug)]
pub struct Experiments {
// Add experimental flags here, to provide access to them through-out the GraphQL
// implementation.
#[cfg(test)]
test_flag: bool,
}

#[GraphQLConfig]
#[DefaultConfig]
#[derive(Clone, Debug)]
pub struct InternalFeatureConfig {
pub(crate) query_limits_checker: bool,
pub(crate) directive_checker: bool,
Expand All @@ -215,16 +217,16 @@ pub struct InternalFeatureConfig {
pub(crate) open_telemetry: bool,
}

#[GraphQLConfig]
#[derive(clap::Args, Default)]
#[DefaultConfig]
#[derive(clap::Args, Clone, Default, Debug)]
pub struct TxExecFullNodeConfig {
/// RPC URL for the fullnode to send transactions to execute and dry-run.
#[clap(long)]
pub(crate) node_rpc_url: Option<String>,
}

#[GraphQLConfig]
#[derive(Default)]
#[DefaultConfig]
#[derive(Clone, Default, Eq, PartialEq, Debug)]
pub struct ZkLoginConfig {
pub env: ZkLoginEnv,
}
Expand Down
2 changes: 1 addition & 1 deletion crates/sui-mvr-graphql-rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ uuid.workspace = true
im.workspace = true
downcast = "0.11.0"

sui-graphql-config.workspace = true
sui-default-config.workspace = true
sui-graphql-rpc-headers.workspace = true
sui-graphql-rpc-client.workspace = true

Expand Down
Loading