From 1e5c1cc317355664ecec320c1fd82e7e3840abf0 Mon Sep 17 00:00:00 2001 From: Ashok Menon Date: Sat, 23 Nov 2024 01:24:07 +0000 Subject: [PATCH 1/3] indexer-alt: generalize GraphQLConfig ## Description `GraphQLConfig` is a derive macro for deriving `Serialize`, `Deserialize`, and `Debug`, and introducing `#[serde(default = ...)]` annotations that rely on the fields of the type's `Default` implementation. This allows config types to rely on their `Default` implementation as a single source of truth for default values, and is used through-out `sui-graphql-rpc` to define its config types. This change generalizes it (renames it) so it can be used in the indexer as well. ## Test plan Build and test `sui-graphql-rpc`, `sui-mvr-graphql-rpc`: ``` sui$ cargo nextest run -p sui-graphql-rpc sui$ cargo nextest run -p sui-graphql-e2e-tests sui$ cargo nextest run -p sui-mvr-graphql-rpc ``` This is a behaviour preserving change for the moment. --- Cargo.lock | 20 ++++++++-------- Cargo.toml | 4 ++-- .../Cargo.toml | 2 +- .../src/lib.rs | 6 ++--- crates/sui-graphql-rpc/Cargo.toml | 2 +- crates/sui-graphql-rpc/src/config.rs | 24 +++++++++---------- crates/sui-mvr-graphql-rpc/Cargo.toml | 2 +- crates/sui-mvr-graphql-rpc/src/config.rs | 24 +++++++++---------- 8 files changed, 42 insertions(+), 42 deletions(-) rename crates/{sui-graphql-config => sui-default-config}/Cargo.toml (88%) rename crates/{sui-graphql-config => sui-default-config}/src/lib.rs (95%) diff --git a/Cargo.lock b/Cargo.lock index 18ef4df744233..b27ebd7a56132 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13607,6 +13607,14 @@ dependencies = [ "tracing", ] +[[package]] +name = "sui-default-config" +version = "1.39.0" +dependencies = [ + "quote 1.0.35", + "syn 1.0.107", +] + [[package]] name = "sui-e2e-tests" version = "1.39.0" @@ -13865,14 +13873,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "sui-graphql-config" -version = "1.39.0" -dependencies = [ - "quote 1.0.35", - "syn 1.0.107", -] - [[package]] name = "sui-graphql-e2e-tests" version = "0.1.0" @@ -13935,8 +13935,8 @@ dependencies = [ "shared-crypto", "similar", "simulacrum", + "sui-default-config", "sui-framework", - "sui-graphql-config", "sui-graphql-rpc-client", "sui-graphql-rpc-headers", "sui-indexer", @@ -14590,8 +14590,8 @@ dependencies = [ "shared-crypto", "similar", "simulacrum", + "sui-default-config", "sui-framework", - "sui-graphql-config", "sui-graphql-rpc-client", "sui-graphql-rpc-headers", "sui-indexer", diff --git a/Cargo.toml b/Cargo.toml index c33adee27a8a6..d210b8214fbb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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", @@ -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", @@ -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" } @@ -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" } diff --git a/crates/sui-graphql-config/Cargo.toml b/crates/sui-default-config/Cargo.toml similarity index 88% rename from crates/sui-graphql-config/Cargo.toml rename to crates/sui-default-config/Cargo.toml index 0f20ce1769a94..8b0424bf5cbca 100644 --- a/crates/sui-graphql-config/Cargo.toml +++ b/crates/sui-default-config/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "sui-graphql-config" +name = "sui-default-config" version.workspace = true authors = ["Mysten Labs TokenStream { +pub fn DefaultConfig(_attr: TokenStream, input: TokenStream) -> TokenStream { let DeriveInput { attrs, vis, @@ -32,7 +32,7 @@ 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 { @@ -40,7 +40,7 @@ pub fn GraphQLConfig(_attr: TokenStream, input: TokenStream) -> TokenStream { 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. diff --git a/crates/sui-graphql-rpc/Cargo.toml b/crates/sui-graphql-rpc/Cargo.toml index f1c2b67842897..f58bd12123949 100644 --- a/crates/sui-graphql-rpc/Cargo.toml +++ b/crates/sui-graphql-rpc/Cargo.toml @@ -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 diff --git a/crates/sui-graphql-rpc/src/config.rs b/crates/sui-graphql-rpc/src/config.rs index cb9602fd7a0c6..e1b3987434b34 100644 --- a/crates/sui-graphql-rpc/src/config.rs +++ b/crates/sui-graphql-rpc/src/config.rs @@ -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}; @@ -28,7 +28,7 @@ const MOVE_REGISTRY_TABLE_ID: &str = const DEFAULT_PAGE_LIMIT: u16 = 50; /// The combination of all configurations for the GraphQL service. -#[GraphQLConfig] +#[DefaultConfig] #[derive(Default)] pub struct ServerConfig { pub service: ServiceConfig, @@ -41,7 +41,7 @@ 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] +#[DefaultConfig] #[derive(clap::Args, Clone, Eq, PartialEq)] pub struct ConnectionConfig { /// Port to bind the server to @@ -71,7 +71,7 @@ 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] +#[DefaultConfig] #[derive(Default)] pub struct ServiceConfig { pub limits: Limits, @@ -83,7 +83,7 @@ pub struct ServiceConfig { pub move_registry: MoveRegistryConfig, } -#[GraphQLConfig] +#[DefaultConfig] pub struct Limits { /// Maximum depth of nodes in the requests. pub max_query_depth: u32, @@ -127,7 +127,7 @@ pub struct Limits { pub max_scan_limit: u32, } -#[GraphQLConfig] +#[DefaultConfig] #[derive(Copy)] pub struct BackgroundTasksConfig { /// How often the watermark task checks the indexer database to update the checkpoint and epoch @@ -135,7 +135,7 @@ pub struct BackgroundTasksConfig { pub watermark_update_ms: u64, } -#[GraphQLConfig] +#[DefaultConfig] #[derive(Clone)] pub struct MoveRegistryConfig { pub(crate) external_api_url: Option, @@ -185,7 +185,7 @@ impl Version { } } -#[GraphQLConfig] +#[DefaultConfig] #[derive(clap::Args)] pub struct Ide { /// The title to display at the top of the web-based GraphiQL IDE. @@ -193,7 +193,7 @@ pub struct Ide { pub ide_title: String, } -#[GraphQLConfig] +#[DefaultConfig] #[derive(Default)] pub struct Experiments { // Add experimental flags here, to provide access to them through-out the GraphQL @@ -202,7 +202,7 @@ pub struct Experiments { test_flag: bool, } -#[GraphQLConfig] +#[DefaultConfig] pub struct InternalFeatureConfig { pub(crate) query_limits_checker: bool, pub(crate) directive_checker: bool, @@ -215,7 +215,7 @@ pub struct InternalFeatureConfig { pub(crate) open_telemetry: bool, } -#[GraphQLConfig] +#[DefaultConfig] #[derive(clap::Args, Default)] pub struct TxExecFullNodeConfig { /// RPC URL for the fullnode to send transactions to execute and dry-run. @@ -223,7 +223,7 @@ pub struct TxExecFullNodeConfig { pub(crate) node_rpc_url: Option, } -#[GraphQLConfig] +#[DefaultConfig] #[derive(Default)] pub struct ZkLoginConfig { pub env: ZkLoginEnv, diff --git a/crates/sui-mvr-graphql-rpc/Cargo.toml b/crates/sui-mvr-graphql-rpc/Cargo.toml index 5db654e5122c1..39c88e978766f 100644 --- a/crates/sui-mvr-graphql-rpc/Cargo.toml +++ b/crates/sui-mvr-graphql-rpc/Cargo.toml @@ -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 diff --git a/crates/sui-mvr-graphql-rpc/src/config.rs b/crates/sui-mvr-graphql-rpc/src/config.rs index cb9602fd7a0c6..e1b3987434b34 100644 --- a/crates/sui-mvr-graphql-rpc/src/config.rs +++ b/crates/sui-mvr-graphql-rpc/src/config.rs @@ -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}; @@ -28,7 +28,7 @@ const MOVE_REGISTRY_TABLE_ID: &str = const DEFAULT_PAGE_LIMIT: u16 = 50; /// The combination of all configurations for the GraphQL service. -#[GraphQLConfig] +#[DefaultConfig] #[derive(Default)] pub struct ServerConfig { pub service: ServiceConfig, @@ -41,7 +41,7 @@ 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] +#[DefaultConfig] #[derive(clap::Args, Clone, Eq, PartialEq)] pub struct ConnectionConfig { /// Port to bind the server to @@ -71,7 +71,7 @@ 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] +#[DefaultConfig] #[derive(Default)] pub struct ServiceConfig { pub limits: Limits, @@ -83,7 +83,7 @@ pub struct ServiceConfig { pub move_registry: MoveRegistryConfig, } -#[GraphQLConfig] +#[DefaultConfig] pub struct Limits { /// Maximum depth of nodes in the requests. pub max_query_depth: u32, @@ -127,7 +127,7 @@ pub struct Limits { pub max_scan_limit: u32, } -#[GraphQLConfig] +#[DefaultConfig] #[derive(Copy)] pub struct BackgroundTasksConfig { /// How often the watermark task checks the indexer database to update the checkpoint and epoch @@ -135,7 +135,7 @@ pub struct BackgroundTasksConfig { pub watermark_update_ms: u64, } -#[GraphQLConfig] +#[DefaultConfig] #[derive(Clone)] pub struct MoveRegistryConfig { pub(crate) external_api_url: Option, @@ -185,7 +185,7 @@ impl Version { } } -#[GraphQLConfig] +#[DefaultConfig] #[derive(clap::Args)] pub struct Ide { /// The title to display at the top of the web-based GraphiQL IDE. @@ -193,7 +193,7 @@ pub struct Ide { pub ide_title: String, } -#[GraphQLConfig] +#[DefaultConfig] #[derive(Default)] pub struct Experiments { // Add experimental flags here, to provide access to them through-out the GraphQL @@ -202,7 +202,7 @@ pub struct Experiments { test_flag: bool, } -#[GraphQLConfig] +#[DefaultConfig] pub struct InternalFeatureConfig { pub(crate) query_limits_checker: bool, pub(crate) directive_checker: bool, @@ -215,7 +215,7 @@ pub struct InternalFeatureConfig { pub(crate) open_telemetry: bool, } -#[GraphQLConfig] +#[DefaultConfig] #[derive(clap::Args, Default)] pub struct TxExecFullNodeConfig { /// RPC URL for the fullnode to send transactions to execute and dry-run. @@ -223,7 +223,7 @@ pub struct TxExecFullNodeConfig { pub(crate) node_rpc_url: Option, } -#[GraphQLConfig] +#[DefaultConfig] #[derive(Default)] pub struct ZkLoginConfig { pub env: ZkLoginEnv, From e81e26e23f10f6d8bdb1e4937c6a8f605e6640bc Mon Sep 17 00:00:00 2001 From: Ashok Menon Date: Sun, 24 Nov 2024 18:33:39 +0000 Subject: [PATCH 2/3] indexer-alt: sui-default-config simplify auto-derives ## Description `DefaultConfig` previously automatically added derives for `Serialize`, `Deserialize`, and `Clone`, `Eq` and `PartialEq`, which was convenient for its use in `sui-graphql-rpc`, but it does not generalize well, because: - Currently, it requires that the traits are in scope, which somewhat defeats the point of not having to explicitly derive them, in the case of `Serialize`/`Deserialize`. - The logic to detect when a derive is already applied is fragile, because it works by name (so it wouldn't play nicely with fully-qualified or aliased derives). This change removes that support in favour of a simpler approach: - `DefaultConfig` adds derives for `serde::Serialize` and `serde::Deserialize`, using fully-qualified names. - Other derives need to be added explicitly. - The logic to only add a derive if it hasn't already been added has been removed. ## Test plan CI for existing use cases. --- crates/sui-default-config/src/lib.rs | 57 ++---------------------- crates/sui-graphql-rpc/src/config.rs | 20 +++++---- crates/sui-mvr-graphql-rpc/src/config.rs | 20 +++++---- 3 files changed, 25 insertions(+), 72 deletions(-) diff --git a/crates/sui-default-config/src/lib.rs b/crates/sui-default-config/src/lib.rs index 0eafd5ddd480d..53b304170a67f 100644 --- a/crates/sui-default-config/src/lib.rs +++ b/crates/sui-default-config/src/lib.rs @@ -1,14 +1,9 @@ // 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, -}; +use syn::{parse_macro_input, Attribute, Data, DataStruct, DeriveInput, Fields, FieldsNamed}; /// Attribute macro to be applied to config-based structs. It ensures that the struct derives serde /// traits, and `Debug`, that all fields are renamed with "kebab case", and adds a `#[serde(default @@ -43,9 +38,6 @@ pub fn DefaultConfig(_attr: TokenStream, input: TokenStream) -> TokenStream { 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() @@ -73,13 +65,13 @@ pub fn DefaultConfig(_attr: TokenStream, input: TokenStream) -> TokenStream { quote! { #[doc(hidden)] #cfg fn #fn_name() -> #ty { - Self::default().#name + ::default().#name } } }); TokenStream::from(quote! { - #[derive(#(#core_derives),*)] + #[derive(serde::Serialize, serde::Deserialize)] #[serde(rename_all = "kebab-case")] #(#attrs)* #vis #struct_token #ident #generics { #(#fields),* @@ -91,49 +83,6 @@ pub fn DefaultConfig(_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 { - 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| { diff --git a/crates/sui-graphql-rpc/src/config.rs b/crates/sui-graphql-rpc/src/config.rs index e1b3987434b34..56304bd2fd65e 100644 --- a/crates/sui-graphql-rpc/src/config.rs +++ b/crates/sui-graphql-rpc/src/config.rs @@ -29,7 +29,7 @@ const DEFAULT_PAGE_LIMIT: u16 = 50; /// The combination of all configurations for the GraphQL service. #[DefaultConfig] -#[derive(Default)] +#[derive(Clone, Default, Debug)] pub struct ServerConfig { pub service: ServiceConfig, pub connection: ConnectionConfig, @@ -42,7 +42,7 @@ pub struct ServerConfig { /// specific connections between this service and other services, and might differ from instance to /// instance of the GraphQL service. #[DefaultConfig] -#[derive(clap::Args, Clone, Eq, PartialEq)] +#[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)] @@ -72,7 +72,7 @@ pub struct ConnectionConfig { /// configurations are shared across fleets of the service, i.e. all testnet services will have the /// same `ServiceConfig`. #[DefaultConfig] -#[derive(Default)] +#[derive(Clone, Default, Eq, PartialEq, Debug)] pub struct ServiceConfig { pub limits: Limits, pub disabled_features: BTreeSet, @@ -84,6 +84,7 @@ pub struct ServiceConfig { } #[DefaultConfig] +#[derive(Clone, Eq, PartialEq, Debug)] pub struct Limits { /// Maximum depth of nodes in the requests. pub max_query_depth: u32, @@ -128,7 +129,7 @@ pub struct Limits { } #[DefaultConfig] -#[derive(Copy)] +#[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. @@ -136,7 +137,7 @@ pub struct BackgroundTasksConfig { } #[DefaultConfig] -#[derive(Clone)] +#[derive(Clone, Eq, PartialEq, Debug)] pub struct MoveRegistryConfig { pub(crate) external_api_url: Option, pub(crate) resolution_type: ResolutionType, @@ -186,7 +187,7 @@ impl Version { } #[DefaultConfig] -#[derive(clap::Args)] +#[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)] @@ -194,7 +195,7 @@ pub struct Ide { } #[DefaultConfig] -#[derive(Default)] +#[derive(Clone, Default, Eq, PartialEq, Debug)] pub struct Experiments { // Add experimental flags here, to provide access to them through-out the GraphQL // implementation. @@ -203,6 +204,7 @@ pub struct Experiments { } #[DefaultConfig] +#[derive(Clone, Debug)] pub struct InternalFeatureConfig { pub(crate) query_limits_checker: bool, pub(crate) directive_checker: bool, @@ -216,7 +218,7 @@ pub struct InternalFeatureConfig { } #[DefaultConfig] -#[derive(clap::Args, Default)] +#[derive(clap::Args, Clone, Default, Debug)] pub struct TxExecFullNodeConfig { /// RPC URL for the fullnode to send transactions to execute and dry-run. #[clap(long)] @@ -224,7 +226,7 @@ pub struct TxExecFullNodeConfig { } #[DefaultConfig] -#[derive(Default)] +#[derive(Clone, Default, Eq, PartialEq, Debug)] pub struct ZkLoginConfig { pub env: ZkLoginEnv, } diff --git a/crates/sui-mvr-graphql-rpc/src/config.rs b/crates/sui-mvr-graphql-rpc/src/config.rs index e1b3987434b34..56304bd2fd65e 100644 --- a/crates/sui-mvr-graphql-rpc/src/config.rs +++ b/crates/sui-mvr-graphql-rpc/src/config.rs @@ -29,7 +29,7 @@ const DEFAULT_PAGE_LIMIT: u16 = 50; /// The combination of all configurations for the GraphQL service. #[DefaultConfig] -#[derive(Default)] +#[derive(Clone, Default, Debug)] pub struct ServerConfig { pub service: ServiceConfig, pub connection: ConnectionConfig, @@ -42,7 +42,7 @@ pub struct ServerConfig { /// specific connections between this service and other services, and might differ from instance to /// instance of the GraphQL service. #[DefaultConfig] -#[derive(clap::Args, Clone, Eq, PartialEq)] +#[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)] @@ -72,7 +72,7 @@ pub struct ConnectionConfig { /// configurations are shared across fleets of the service, i.e. all testnet services will have the /// same `ServiceConfig`. #[DefaultConfig] -#[derive(Default)] +#[derive(Clone, Default, Eq, PartialEq, Debug)] pub struct ServiceConfig { pub limits: Limits, pub disabled_features: BTreeSet, @@ -84,6 +84,7 @@ pub struct ServiceConfig { } #[DefaultConfig] +#[derive(Clone, Eq, PartialEq, Debug)] pub struct Limits { /// Maximum depth of nodes in the requests. pub max_query_depth: u32, @@ -128,7 +129,7 @@ pub struct Limits { } #[DefaultConfig] -#[derive(Copy)] +#[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. @@ -136,7 +137,7 @@ pub struct BackgroundTasksConfig { } #[DefaultConfig] -#[derive(Clone)] +#[derive(Clone, Eq, PartialEq, Debug)] pub struct MoveRegistryConfig { pub(crate) external_api_url: Option, pub(crate) resolution_type: ResolutionType, @@ -186,7 +187,7 @@ impl Version { } #[DefaultConfig] -#[derive(clap::Args)] +#[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)] @@ -194,7 +195,7 @@ pub struct Ide { } #[DefaultConfig] -#[derive(Default)] +#[derive(Clone, Default, Eq, PartialEq, Debug)] pub struct Experiments { // Add experimental flags here, to provide access to them through-out the GraphQL // implementation. @@ -203,6 +204,7 @@ pub struct Experiments { } #[DefaultConfig] +#[derive(Clone, Debug)] pub struct InternalFeatureConfig { pub(crate) query_limits_checker: bool, pub(crate) directive_checker: bool, @@ -216,7 +218,7 @@ pub struct InternalFeatureConfig { } #[DefaultConfig] -#[derive(clap::Args, Default)] +#[derive(clap::Args, Clone, Default, Debug)] pub struct TxExecFullNodeConfig { /// RPC URL for the fullnode to send transactions to execute and dry-run. #[clap(long)] @@ -224,7 +226,7 @@ pub struct TxExecFullNodeConfig { } #[DefaultConfig] -#[derive(Default)] +#[derive(Clone, Default, Eq, PartialEq, Debug)] pub struct ZkLoginConfig { pub env: ZkLoginEnv, } From ad676836b4b1d541caa70ca875c6469d26ab022f Mon Sep 17 00:00:00 2001 From: Ashok Menon Date: Mon, 25 Nov 2024 23:44:12 +0000 Subject: [PATCH 3/3] indexer-alt: support custom renaming of config fields ## Description Add support to `sui-default-config` to change the naming scheme of its fields (previously always used kebab-case). This allows pipelines to retain the names they were given in source code (which use underscores). ## Test plan Will be used and tested in a future PR. --- crates/sui-default-config/src/lib.rs | 33 ++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/crates/sui-default-config/src/lib.rs b/crates/sui-default-config/src/lib.rs index 53b304170a67f..de26d021646ea 100644 --- a/crates/sui-default-config/src/lib.rs +++ b/crates/sui-default-config/src/lib.rs @@ -3,7 +3,10 @@ use proc_macro::TokenStream; use quote::{format_ident, quote}; -use syn::{parse_macro_input, Attribute, Data, DataStruct, DeriveInput, Fields, FieldsNamed}; +use syn::{ + 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 /// traits, and `Debug`, that all fields are renamed with "kebab case", and adds a `#[serde(default @@ -70,9 +73,35 @@ pub fn DefaultConfig(_attr: TokenStream, input: TokenStream) -> TokenStream { } }); + // 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(serde::Serialize, serde::Deserialize)] - #[serde(rename_all = "kebab-case")] + #rename_all #(#attrs)* #vis #struct_token #ident #generics { #(#fields),* } #semi_token