From a5b8e86aeeca46af537071719b3faa0de0671964 Mon Sep 17 00:00:00 2001 From: Ashok Menon Date: Wed, 26 Jun 2024 13:55:47 +0100 Subject: [PATCH] [pick #18347][GraphQL] Fix bug where config types "zero out" fields not in TOML (#18380) ## Description When a field is labeled with `#[serde(default)]` it means that if that field is not present, it is populated using the `Default` impl for the field's type: ```rust #[derive(Serialize, Deserialize, Clone, Debug)] struct Foo { #[serde(default)] bar: Bar, } Foo { bar: Bar::default() } ``` This is not the behaviour we want, however. We want fields that have not been supplied to be populated with their value from the `Default` impl of the type they are part of: ```rust Foo { bar: Foo::default().bar } ``` Implementing this manually requires a lot of boilerplate -- each field needs to have an associated function that returns its default value: ```rust #[derive(Serialize, Deserialize, Clone, Debug)] struct Foo { #[serde(default = "Foo::__default_bar")] bar: Bar, } ``` So this PR introduces an attribute proc macro to perform this transformation: ```rust #[GraphQLConfig] struct Foo { bar: Bar, } ``` It also performs some other related clean-ups: - Moves default values inline into the respective `Default` impls, to prevent them being used in isolation. - Move the documentation for what the field is onto the struct definition, and the documentation for how the default was chosen onto the `Default` impl. - Moved the implementation of `Display` for `Version`. - Got rid of `ConnectionConfig::ci_integration_test_cfg` as it is the same as its `Default` impl now. - Improved various docs about what various configs are. ## Test plan Added a test for reading a `ServiceConfig` from an incomplete/partial TOML: ```sh sui-graphql-rpc$ cargo nextest run -- read_partial_in_service_config ``` --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [x] GraphQL: Fix a bug where starting the service using a config with not all fields set would result in the unset fields being zeroed out rather than taking their usual default values (as would happen if no config had been explicitly supplied). - [ ] CLI: - [ ] Rust SDK: --- Cargo.lock | 9 + Cargo.toml | 2 + crates/sui-graphql-config/Cargo.toml | 14 + crates/sui-graphql-config/src/lib.rs | 143 ++++++++++ crates/sui-graphql-rpc/Cargo.toml | 1 + crates/sui-graphql-rpc/src/config.rs | 244 ++++++++---------- .../src/context_data/db_data_provider.rs | 9 - crates/sui-graphql-rpc/src/data/pg.rs | 10 +- crates/sui-graphql-rpc/src/server/builder.rs | 24 +- crates/sui-graphql-rpc/src/server/version.rs | 2 +- crates/sui-graphql-rpc/tests/e2e_tests.rs | 48 ++-- .../tests/examples_validation_tests.rs | 8 +- 12 files changed, 323 insertions(+), 191 deletions(-) create mode 100644 crates/sui-graphql-config/Cargo.toml create mode 100644 crates/sui-graphql-config/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 04b67d1f3e733..c3b6bd772c6a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12629,6 +12629,14 @@ dependencies = [ "tracing", ] +[[package]] +name = "sui-graphql-config" +version = "1.24.0" +dependencies = [ + "quote 1.0.35", + "syn 1.0.107", +] + [[package]] name = "sui-graphql-e2e-tests" version = "0.1.0" @@ -12691,6 +12699,7 @@ dependencies = [ "similar", "simulacrum", "sui-framework", + "sui-graphql-config", "sui-graphql-rpc-client", "sui-graphql-rpc-headers", "sui-indexer", diff --git a/Cargo.toml b/Cargo.toml index 01809b8883ba0..4668965be9281 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -107,6 +107,7 @@ 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", @@ -600,6 +601,7 @@ sui-faucet = { path = "crates/sui-faucet" } 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-graphql-config/Cargo.toml new file mode 100644 index 0000000000000..0f20ce1769a94 --- /dev/null +++ b/crates/sui-graphql-config/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "sui-graphql-config" +version.workspace = true +authors = ["Mysten Labs TokenStream { + let DeriveInput { + attrs, + vis, + ident, + generics, + data, + } = parse_macro_input!(input as DeriveInput); + + let Data::Struct(DataStruct { + struct_token, + fields, + semi_token, + }) = data + else { + panic!("GraphQL configs must be structs."); + }; + + let Fields::Named(FieldsNamed { + brace_token: _, + named, + }) = fields + else { + panic!("GraphQL 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() + .map(|field| { + let Some(ident) = &field.ident else { + panic!("All fields must have an identifier."); + }; + + (ident, field) + }) + .collect(); + + // Generate the fields with the `#[serde(default = ...)]` attribute. + let fields = fields_with_names.iter().map(|(name, field)| { + let default = format!("{ident}::__default_{name}"); + quote! { #[serde(default = #default)] #field } + }); + + // Generate the default implementations for each field. + let defaults = fields_with_names.iter().map(|(name, field)| { + let ty = &field.ty; + let fn_name = format_ident!("__default_{}", name); + let cfg = extract_cfg(&field.attrs); + + quote! { + #[doc(hidden)] #cfg + fn #fn_name() -> #ty { + Self::default().#name + } + } + }); + + TokenStream::from(quote! { + #[derive(#(#core_derives),*)] + #[serde(rename_all = "kebab-case")] + #(#attrs)* #vis #struct_token #ident #generics { + #(#fields),* + } #semi_token + + impl #ident { + #(#defaults)* + } + }) +} + +/// 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| { + let meta = attr.parse_meta().ok(); + meta.is_some_and(|m| m.path().is_ident("cfg")) + }) +} diff --git a/crates/sui-graphql-rpc/Cargo.toml b/crates/sui-graphql-rpc/Cargo.toml index 7921a3ffb8d1e..30166b3fb53f7 100644 --- a/crates/sui-graphql-rpc/Cargo.toml +++ b/crates/sui-graphql-rpc/Cargo.toml @@ -63,6 +63,7 @@ uuid.workspace = true im.workspace = true downcast = "0.11.0" +sui-graphql-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 326f9bb3ea75a..c4bb5e086be40 100644 --- a/crates/sui-graphql-rpc/src/config.rs +++ b/crates/sui-graphql-rpc/src/config.rs @@ -7,70 +7,28 @@ use async_graphql::*; use fastcrypto_zkp::bn254::zk_login_api::ZkLoginEnv; use serde::{Deserialize, Serialize}; use std::{collections::BTreeSet, fmt::Display, time::Duration}; +use sui_graphql_config::GraphQLConfig; use sui_json_rpc::name_service::NameServiceConfig; -// TODO: calculate proper cost limits - -/// These values are set to support TS SDK shim layer queries for json-rpc compatibility. -const MAX_QUERY_NODES: u32 = 300; -const MAX_QUERY_PAYLOAD_SIZE: u32 = 5_000; - -const MAX_QUERY_DEPTH: u32 = 20; -const MAX_OUTPUT_NODES: u64 = 100_000; // Maximum number of output nodes allowed in the response -const MAX_DB_QUERY_COST: u64 = 20_000; // Max DB query cost (normally f64) truncated -const DEFAULT_PAGE_SIZE: u64 = 20; // Default number of elements allowed on a page of a connection -const MAX_PAGE_SIZE: u64 = 50; // Maximum number of elements allowed on a page of a connection - -/// The following limits reflect the max values set in the ProtocolConfig. -const MAX_TYPE_ARGUMENT_DEPTH: u32 = 16; -const MAX_TYPE_ARGUMENT_WIDTH: u32 = 32; -const MAX_TYPE_NODES: u32 = 256; -const MAX_MOVE_VALUE_DEPTH: u32 = 128; - -pub(crate) const DEFAULT_REQUEST_TIMEOUT_MS: u64 = 40_000; - -/// The time to wait for a transaction to be executed such that the effects can be returned to the -/// GraphQL query. If the transaction takes longer than this time to execute, the query will return -/// a timeout error, but the transaction will continue its execution. -/// -/// It's the sum of pre+post quorum timeouts from [`sui_core::authority_aggregator::TimeoutConfig`] -/// plus a small buffer of 10% rounded up: 60 + 7 => round_up(67 * 1.1) = 74 -/// -pub(crate) const DEFAULT_MUTATION_TIMEOUT_MS: u64 = 74_000; - -const DEFAULT_IDE_TITLE: &str = "Sui GraphQL IDE"; pub(crate) const RPC_TIMEOUT_ERR_SLEEP_RETRY_PERIOD: Duration = Duration::from_millis(10_000); pub(crate) const MAX_CONCURRENT_REQUESTS: usize = 1_000; -// Default values for the server connection configuration. -pub(crate) const DEFAULT_SERVER_CONNECTION_PORT: u16 = 8000; -pub(crate) const DEFAULT_SERVER_CONNECTION_HOST: &str = "127.0.0.1"; -pub(crate) const DEFAULT_SERVER_DB_URL: &str = - "postgres://postgres:postgrespw@localhost:5432/sui_indexer"; -pub(crate) const DEFAULT_SERVER_DB_POOL_SIZE: u32 = 10; -pub(crate) const DEFAULT_SERVER_PROM_HOST: &str = "0.0.0.0"; -pub(crate) const DEFAULT_SERVER_PROM_PORT: u16 = 9184; -pub(crate) const DEFAULT_WATERMARK_UPDATE_MS: u64 = 500; - /// The combination of all configurations for the GraphQL service. -#[derive(Serialize, Clone, Deserialize, Debug, Default)] +#[GraphQLConfig] +#[derive(Default)] pub struct ServerConfig { - #[serde(default)] pub service: ServiceConfig, - #[serde(default)] pub connection: ConnectionConfig, - #[serde(default)] pub internal_features: InternalFeatureConfig, - #[serde(default)] pub tx_exec_full_node: TxExecFullNodeConfig, - #[serde(default)] pub ide: Ide, } /// 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. -#[derive(Serialize, Clone, Deserialize, Debug, Eq, PartialEq)] +#[GraphQLConfig] +#[derive(Clone, Eq, PartialEq)] pub struct ConnectionConfig { /// Port to bind the server to pub(crate) port: u16, @@ -85,73 +43,63 @@ 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`. -#[derive(Serialize, Clone, Deserialize, Debug, Eq, PartialEq, Default)] -#[serde(rename_all = "kebab-case")] +#[GraphQLConfig] +#[derive(Default)] pub struct ServiceConfig { - #[serde(default)] pub(crate) versions: Versions, - - #[serde(default)] pub(crate) limits: Limits, - - #[serde(default)] pub(crate) disabled_features: BTreeSet, - - #[serde(default)] pub(crate) experiments: Experiments, - - #[serde(default)] pub(crate) name_service: NameServiceConfig, - - #[serde(default)] pub(crate) background_tasks: BackgroundTasksConfig, - - #[serde(default)] pub(crate) zklogin: ZkLoginConfig, } -#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] -#[serde(rename_all = "kebab-case")] +#[GraphQLConfig] pub struct Versions { - #[serde(default)] versions: Vec, } -#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Copy)] -#[serde(rename_all = "kebab-case")] +#[GraphQLConfig] pub struct Limits { - #[serde(default)] + /// Maximum depth of nodes in the requests. pub max_query_depth: u32, - #[serde(default)] + /// Maximum number of nodes in the requests. pub max_query_nodes: u32, - #[serde(default)] + /// Maximum number of output nodes allowed in the response. pub max_output_nodes: u64, - #[serde(default)] + /// Maximum size (in bytes) of a GraphQL request. pub max_query_payload_size: u32, - #[serde(default)] + /// Queries whose EXPLAIN cost are more than this will be logged. Given in the units used by the + /// database (where 1.0 is roughly the cost of a sequential page access). pub max_db_query_cost: u64, - #[serde(default)] + /// Paginated queries will return this many elements if a page size is not provided. pub default_page_size: u64, - #[serde(default)] + /// Paginated queries can return at most this many elements. pub max_page_size: u64, - #[serde(default)] + /// Time (in milliseconds) to wait for a transaction to be executed and the results returned + /// from GraphQL. If the transaction takes longer than this time to execute, the request will + /// return a timeout error, but the transaction may continue executing. pub mutation_timeout_ms: u64, - #[serde(default)] + /// Time (in milliseconds) to wait for a read request from the GraphQL service. Requests that + /// take longer than this time to return a result will return a timeout error. pub request_timeout_ms: u64, - #[serde(default)] + /// Maximum amount of nesting among type arguments (type arguments nest when a type argument is + /// itself generic and has arguments). pub max_type_argument_depth: u32, - #[serde(default)] + /// Maximum number of type parameters a type can have. pub max_type_argument_width: u32, - #[serde(default)] + /// Maximum size of a fully qualified type. pub max_type_nodes: u32, - #[serde(default)] + /// Maximum deph of a move value. pub max_move_value_depth: u32, } -#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Copy)] -#[serde(rename_all = "kebab-case")] +#[GraphQLConfig] +#[derive(Copy)] pub struct BackgroundTasksConfig { - #[serde(default)] + /// How often the watermark task checks the indexer database to update the checkpoint and epoch + /// watermarks. pub watermark_update_ms: u64, } @@ -195,21 +143,13 @@ impl Version { } } -impl Display for Version { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.full) - } -} - -#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] -#[serde(rename_all = "kebab-case")] +#[GraphQLConfig] pub struct Ide { - #[serde(default)] pub(crate) ide_title: String, } -#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Default)] -#[serde(rename_all = "kebab-case")] +#[GraphQLConfig] +#[derive(Default)] pub struct Experiments { // Add experimental flags here, to provide access to them through-out the GraphQL // implementation. @@ -217,34 +157,26 @@ pub struct Experiments { test_flag: bool, } -#[derive(Serialize, Clone, Deserialize, Debug, Eq, PartialEq)] +#[GraphQLConfig] pub struct InternalFeatureConfig { - #[serde(default)] pub(crate) query_limits_checker: bool, - #[serde(default)] pub(crate) feature_gate: bool, - #[serde(default)] pub(crate) logger: bool, - #[serde(default)] pub(crate) query_timeout: bool, - #[serde(default)] pub(crate) metrics: bool, - #[serde(default)] pub(crate) tracing: bool, - #[serde(default)] pub(crate) apollo_tracing: bool, - #[serde(default)] pub(crate) open_telemetry: bool, } -#[derive(Serialize, Clone, Deserialize, Debug, Eq, PartialEq, Default)] +#[GraphQLConfig] +#[derive(Default)] pub struct TxExecFullNodeConfig { - #[serde(default)] pub(crate) node_rpc_url: Option, } -#[derive(Serialize, Clone, Deserialize, Debug, Eq, PartialEq, Default)] -#[serde(rename_all = "kebab-case")] +#[GraphQLConfig] +#[derive(Default)] pub struct ZkLoginConfig { pub env: ZkLoginEnv, } @@ -378,13 +310,6 @@ impl ConnectionConfig { } } - pub fn ci_integration_test_cfg() -> Self { - Self { - db_url: DEFAULT_SERVER_DB_URL.to_string(), - ..Default::default() - } - } - pub fn ci_integration_test_cfg_with_db_name( db_name: String, port: u16, @@ -445,9 +370,9 @@ impl Limits { impl Ide { pub fn new(ide_title: Option) -> Self { - Self { - ide_title: ide_title.unwrap_or_else(|| DEFAULT_IDE_TITLE.to_string()), - } + ide_title + .map(|ide_title| Ide { ide_title }) + .unwrap_or_default() } } @@ -474,7 +399,7 @@ impl Default for Versions { impl Default for Ide { fn default() -> Self { Self { - ide_title: DEFAULT_IDE_TITLE.to_string(), + ide_title: "Sui GraphQL IDE".to_string(), } } } @@ -482,32 +407,43 @@ impl Default for Ide { impl Default for ConnectionConfig { fn default() -> Self { Self { - port: DEFAULT_SERVER_CONNECTION_PORT, - host: DEFAULT_SERVER_CONNECTION_HOST.to_string(), - db_url: DEFAULT_SERVER_DB_URL.to_string(), - db_pool_size: DEFAULT_SERVER_DB_POOL_SIZE, - prom_url: DEFAULT_SERVER_PROM_HOST.to_string(), - prom_port: DEFAULT_SERVER_PROM_PORT, + port: 8000, + host: "127.0.0.1".to_string(), + db_url: "postgres://postgres:postgrespw@localhost:5432/sui_indexer".to_string(), + db_pool_size: 10, + prom_url: "0.0.0.0".to_string(), + prom_port: 9184, } } } impl Default for Limits { fn default() -> Self { + // Picked so that TS SDK shim layer queries all pass limit. + // TODO: calculate proper cost limits Self { - max_query_depth: MAX_QUERY_DEPTH, - max_query_nodes: MAX_QUERY_NODES, - max_output_nodes: MAX_OUTPUT_NODES, - max_query_payload_size: MAX_QUERY_PAYLOAD_SIZE, - max_db_query_cost: MAX_DB_QUERY_COST, - default_page_size: DEFAULT_PAGE_SIZE, - max_page_size: MAX_PAGE_SIZE, - mutation_timeout_ms: DEFAULT_MUTATION_TIMEOUT_MS, - request_timeout_ms: DEFAULT_REQUEST_TIMEOUT_MS, - max_type_argument_depth: MAX_TYPE_ARGUMENT_DEPTH, - max_type_argument_width: MAX_TYPE_ARGUMENT_WIDTH, - max_type_nodes: MAX_TYPE_NODES, - max_move_value_depth: MAX_MOVE_VALUE_DEPTH, + max_query_depth: 20, + max_query_nodes: 300, + max_output_nodes: 100_000, + max_query_payload_size: 5_000, + max_db_query_cost: 20_000, + default_page_size: 20, + max_page_size: 50, + // This default was picked as the sum of pre- and post- quorum timeouts from + // [`sui_core::authority_aggregator::TimeoutConfig`], with a 10% buffer. + // + // + mutation_timeout_ms: 74_000, + request_timeout_ms: 40_000, + // The following limits reflect the max values set in ProtocolConfig, at time of writing. + // + max_type_argument_depth: 16, + // + max_type_argument_width: 32, + // + max_type_nodes: 256, + // + max_move_value_depth: 128, } } } @@ -530,11 +466,17 @@ impl Default for InternalFeatureConfig { impl Default for BackgroundTasksConfig { fn default() -> Self { Self { - watermark_update_ms: DEFAULT_WATERMARK_UPDATE_MS, + watermark_update_ms: 500, } } } +impl Display for Version { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.full) + } +} + #[cfg(test)] mod tests { use super::*; @@ -675,4 +617,30 @@ mod tests { assert_eq!(actual, expect); } + + #[test] + fn test_read_partial_in_service_config() { + let actual = ServiceConfig::read( + r#" disabled-features = ["analytics"] + + [limits] + max-query-depth = 42 + max-query-nodes = 320 + "#, + ) + .unwrap(); + + // When reading partially, the other parts will come from the default implementation. + let expect = ServiceConfig { + limits: Limits { + max_query_depth: 42, + max_query_nodes: 320, + ..Default::default() + }, + disabled_features: BTreeSet::from([FunctionalGroup::Analytics]), + ..Default::default() + }; + + assert_eq!(actual, expect); + } } diff --git a/crates/sui-graphql-rpc/src/context_data/db_data_provider.rs b/crates/sui-graphql-rpc/src/context_data/db_data_provider.rs index 93e80146eeb02..1a37e58d96981 100644 --- a/crates/sui-graphql-rpc/src/context_data/db_data_provider.rs +++ b/crates/sui-graphql-rpc/src/context_data/db_data_provider.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - config::{DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_SERVER_DB_POOL_SIZE}, error::Error, types::{address::Address, sui_address::SuiAddress, validator::Validator}, }; @@ -26,14 +25,6 @@ impl PgManager { } /// Create a new underlying reader, which is used by this type as well as other data providers. - pub(crate) fn reader(db_url: impl Into) -> Result, Error> { - Self::reader_with_config( - db_url, - DEFAULT_SERVER_DB_POOL_SIZE, - DEFAULT_REQUEST_TIMEOUT_MS, - ) - } - pub(crate) fn reader_with_config( db_url: impl Into, pool_size: u32, diff --git a/crates/sui-graphql-rpc/src/data/pg.rs b/crates/sui-graphql-rpc/src/data/pg.rs index 6fa23847f7516..d9a51f818eb17 100644 --- a/crates/sui-graphql-rpc/src/data/pg.rs +++ b/crates/sui-graphql-rpc/src/data/pg.rs @@ -187,7 +187,7 @@ mod query_cost { #[cfg(all(test, feature = "pg_integration"))] mod tests { use super::*; - use crate::config::DEFAULT_SERVER_DB_URL; + use crate::config::ConnectionConfig; use diesel::QueryDsl; use sui_framework::BuiltInFramework; use sui_indexer::{ @@ -199,8 +199,12 @@ mod tests { #[test] fn test_query_cost() { - let pool = - new_connection_pool::(DEFAULT_SERVER_DB_URL, Some(5)).unwrap(); + let connection_config = ConnectionConfig::default(); + let pool = new_connection_pool::( + &connection_config.db_url, + Some(connection_config.db_pool_size), + ) + .unwrap(); let mut conn = get_pool_connection(&pool).unwrap(); reset_database(&mut conn, /* drop_all */ true).unwrap(); diff --git a/crates/sui-graphql-rpc/src/server/builder.rs b/crates/sui-graphql-rpc/src/server/builder.rs index 337d2c2d3a39a..fc160bcb269c2 100644 --- a/crates/sui-graphql-rpc/src/server/builder.rs +++ b/crates/sui-graphql-rpc/src/server/builder.rs @@ -422,7 +422,11 @@ impl ServerBuilder { .map_err(|e| Error::Internal(format!("Failed to create pg connection pool: {}", e)))?; // DB - let db = Db::new(reader.clone(), config.service.limits, metrics.clone()); + let db = Db::new( + reader.clone(), + config.service.limits.clone(), + metrics.clone(), + ); let loader = DataLoader::new(db.clone()); let pg_conn_pool = PgManager::new(reader.clone()); let package_store = DbPackageStore::new(loader.clone()); @@ -674,15 +678,23 @@ pub mod tests { connection_config: Option, service_config: Option, ) -> ServerBuilder { - let connection_config = - connection_config.unwrap_or_else(ConnectionConfig::ci_integration_test_cfg); + let connection_config = connection_config.unwrap_or_default(); let service_config = service_config.unwrap_or_default(); - let db_url: String = connection_config.db_url.clone(); - let reader = PgManager::reader(db_url).expect("Failed to create pg connection pool"); + let reader = PgManager::reader_with_config( + connection_config.db_url.clone(), + connection_config.db_pool_size, + service_config.limits.request_timeout_ms, + ) + .expect("Failed to create pg connection pool"); + let version = Version::for_testing(); let metrics = metrics(); - let db = Db::new(reader.clone(), service_config.limits, metrics.clone()); + let db = Db::new( + reader.clone(), + service_config.limits.clone(), + metrics.clone(), + ); let pg_conn_pool = PgManager::new(reader); let cancellation_token = CancellationToken::new(); let watermark = Watermark { diff --git a/crates/sui-graphql-rpc/src/server/version.rs b/crates/sui-graphql-rpc/src/server/version.rs index c19a7dc8764ad..46b7bf32be05b 100644 --- a/crates/sui-graphql-rpc/src/server/version.rs +++ b/crates/sui-graphql-rpc/src/server/version.rs @@ -149,7 +149,7 @@ mod tests { let version = Version::for_testing(); let metrics = metrics(); let cancellation_token = CancellationToken::new(); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); + let connection_config = ConnectionConfig::default(); let service_config = ServiceConfig::default(); let state = AppState::new( connection_config.clone(), diff --git a/crates/sui-graphql-rpc/tests/e2e_tests.rs b/crates/sui-graphql-rpc/tests/e2e_tests.rs index e05434eb686b0..5ec6c48705f27 100644 --- a/crates/sui-graphql-rpc/tests/e2e_tests.rs +++ b/crates/sui-graphql-rpc/tests/e2e_tests.rs @@ -36,8 +36,7 @@ mod tests { sim.create_checkpoint(); sim.create_checkpoint(); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); - + let connection_config = ConnectionConfig::default(); let cluster = sui_graphql_rpc::test_infra::cluster::serve_executor( connection_config.clone(), DEFAULT_INTERNAL_DATA_SOURCE_PORT, @@ -61,10 +60,9 @@ mod tests { .with_env() .init(); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); - let cluster = - sui_graphql_rpc::test_infra::cluster::start_cluster(connection_config, None).await; + sui_graphql_rpc::test_infra::cluster::start_cluster(ConnectionConfig::default(), None) + .await; cluster .wait_for_checkpoint_catchup(0, Duration::from_secs(10)) @@ -118,9 +116,8 @@ mod tests { "{{\"data\":{{\"chainIdentifier\":\"{}\"}}}}", chain_id_actual ); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); let cluster = sui_graphql_rpc::test_infra::cluster::serve_executor( - connection_config, + ConnectionConfig::default(), DEFAULT_INTERNAL_DATA_SOURCE_PORT, Arc::new(sim), None, @@ -321,10 +318,9 @@ mod tests { .with_env() .init(); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); - let cluster = - sui_graphql_rpc::test_infra::cluster::start_cluster(connection_config, None).await; + sui_graphql_rpc::test_infra::cluster::start_cluster(ConnectionConfig::default(), None) + .await; let addresses = cluster.validator_fullnode_handle.wallet.get_addresses(); @@ -432,9 +428,9 @@ mod tests { .with_env() .init(); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); let cluster = - sui_graphql_rpc::test_infra::cluster::start_cluster(connection_config, None).await; + sui_graphql_rpc::test_infra::cluster::start_cluster(ConnectionConfig::default(), None) + .await; let test_cluster = cluster.validator_fullnode_handle; test_cluster.wait_for_epoch_all_nodes(1).await; @@ -545,10 +541,9 @@ mod tests { .with_env() .init(); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); - let cluster = - sui_graphql_rpc::test_infra::cluster::start_cluster(connection_config, None).await; + sui_graphql_rpc::test_infra::cluster::start_cluster(ConnectionConfig::default(), None) + .await; let addresses = cluster.validator_fullnode_handle.wallet.get_addresses(); @@ -639,10 +634,9 @@ mod tests { .with_env() .init(); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); - let cluster = - sui_graphql_rpc::test_infra::cluster::start_cluster(connection_config, None).await; + sui_graphql_rpc::test_infra::cluster::start_cluster(ConnectionConfig::default(), None) + .await; let addresses = cluster.validator_fullnode_handle.wallet.get_addresses(); @@ -710,10 +704,9 @@ mod tests { .with_env() .init(); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); - let cluster = - sui_graphql_rpc::test_infra::cluster::start_cluster(connection_config, None).await; + sui_graphql_rpc::test_infra::cluster::start_cluster(ConnectionConfig::default(), None) + .await; let addresses = cluster.validator_fullnode_handle.wallet.get_addresses(); @@ -798,10 +791,9 @@ mod tests { .with_env() .init(); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); - let cluster = - sui_graphql_rpc::test_infra::cluster::start_cluster(connection_config, None).await; + sui_graphql_rpc::test_infra::cluster::start_cluster(ConnectionConfig::default(), None) + .await; cluster .validator_fullnode_handle @@ -845,9 +837,9 @@ mod tests { let _guard = telemetry_subscribers::TelemetryConfig::new() .with_env() .init(); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); let cluster = - sui_graphql_rpc::test_infra::cluster::start_cluster(connection_config, None).await; + sui_graphql_rpc::test_infra::cluster::start_cluster(ConnectionConfig::default(), None) + .await; cluster .wait_for_checkpoint_catchup(0, Duration::from_secs(10)) .await; @@ -894,9 +886,9 @@ mod tests { let _guard = telemetry_subscribers::TelemetryConfig::new() .with_env() .init(); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); let cluster = - sui_graphql_rpc::test_infra::cluster::start_cluster(connection_config, None).await; + sui_graphql_rpc::test_infra::cluster::start_cluster(ConnectionConfig::default(), None) + .await; println!("Cluster started"); cluster diff --git a/crates/sui-graphql-rpc/tests/examples_validation_tests.rs b/crates/sui-graphql-rpc/tests/examples_validation_tests.rs index 5c2e719c4f942..39f3c40ea7b40 100644 --- a/crates/sui-graphql-rpc/tests/examples_validation_tests.rs +++ b/crates/sui-graphql-rpc/tests/examples_validation_tests.rs @@ -110,10 +110,8 @@ mod tests { sim.set_data_ingestion_path(data_ingestion_path.clone()); sim.create_checkpoint(); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); - let cluster = sui_graphql_rpc::test_infra::cluster::serve_executor( - connection_config, + ConnectionConfig::default(), DEFAULT_INTERNAL_DATA_SOURCE_PORT, Arc::new(sim), None, @@ -178,10 +176,8 @@ mod tests { sim.create_checkpoint(); - let connection_config = ConnectionConfig::ci_integration_test_cfg(); - let cluster = sui_graphql_rpc::test_infra::cluster::serve_executor( - connection_config, + ConnectionConfig::default(), DEFAULT_INTERNAL_DATA_SOURCE_PORT, Arc::new(sim), None,