From edf7016a2be8576fb3998ce0f8afd7a24486fc79 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Sat, 24 Jan 2026 15:37:36 -0500 Subject: [PATCH 1/2] perf(index-node): make proofOfIndexing resolver async Remove synchronous `block_on` call in `resolve_proof_of_indexing` which was blocking tokio worker threads while waiting for database queries. Before this change, each POI query blocked an entire tokio worker thread. After this change, POI queries properly yield to the async runtime while waiting for database I/O, allowing the connection pool to be fully utilized. Co-Authored-By: Claude Opus 4.5 --- server/index-node/src/resolver.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/server/index-node/src/resolver.rs b/server/index-node/src/resolver.rs index b8385866d33..3a64552dfe7 100644 --- a/server/index-node/src/resolver.rs +++ b/server/index-node/src/resolver.rs @@ -352,7 +352,10 @@ where )) } - fn resolve_proof_of_indexing(&self, field: &a::Field) -> Result { + async fn resolve_proof_of_indexing( + &self, + field: &a::Field, + ) -> Result { let deployment_id = field .get_required::("subgraph") .expect("Valid subgraphId required"); @@ -381,7 +384,7 @@ where let poi_fut = self .store .get_proof_of_indexing(&deployment_id, &indexer, block.clone()); - let poi = match graph::futures03::executor::block_on(poi_fut) { + let poi = match poi_fut.await { Ok(Some(poi)) => r::Value::String(format!("0x{}", hex::encode(poi))), Ok(None) => r::Value::Null, Err(e) => { @@ -791,7 +794,7 @@ where field.name.as_str(), scalar_type.name.as_str(), ) { - ("Query", "proofOfIndexing", "Bytes") => self.resolve_proof_of_indexing(field), + ("Query", "proofOfIndexing", "Bytes") => self.resolve_proof_of_indexing(field).await, ("Query", "blockData", "JSONObject") => self.resolve_block_data(field).await, ("Query", "blockHashFromNumber", "Bytes") => { self.resolve_block_hash_from_number(field).await From b6cd094fc6e6107924cec21f6caff7f893117ea7 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Sat, 24 Jan 2026 15:38:11 -0500 Subject: [PATCH 2/2] perf(index-node): parallelize publicProofsOfIndexing requests Change the publicProofsOfIndexing resolver to process all POI requests in parallel using `future::join_all` instead of sequentially in a for loop. Co-Authored-By: Claude Opus 4.5 --- server/index-node/src/resolver.rs | 53 ++++++++++++++++--------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/server/index-node/src/resolver.rs b/server/index-node/src/resolver.rs index 3a64552dfe7..542bdf75b0e 100644 --- a/server/index-node/src/resolver.rs +++ b/server/index-node/src/resolver.rs @@ -15,7 +15,7 @@ use graph::components::versions::VERSIONS; use graph::data::graphql::{object, IntoValue, ObjectOrInterface, ValueMap}; use graph::data::subgraph::{status, DeploymentFeatures}; use graph::data::value::Object; -use graph::futures03::TryFutureExt; +use graph::futures03::{future, TryFutureExt}; use graph::prelude::*; use graph_graphql::prelude::{a, ExecutionContext, Resolver}; @@ -417,28 +417,29 @@ where return Err(QueryExecutionError::TooExpensive); } - let mut public_poi_results = vec![]; - for request in requests { - let (poi_result, request) = match self - .store - .get_public_proof_of_indexing(&request.deployment, request.block_number, self) - .await - { - Ok(Some(poi)) => (Some(poi), request), - Ok(None) => (None, request), - Err(e) => { - error!( - self.logger, - "Failed to query public proof of indexing"; - "subgraph" => &request.deployment, - "block" => format!("{}", request.block_number), - "error" => format!("{:?}", e) - ); - (None, request) - } - }; + // Process all POI requests in parallel for better throughput + let poi_futures: Vec<_> = requests + .into_iter() + .map(|request| async move { + let poi_result = match self + .store + .get_public_proof_of_indexing(&request.deployment, request.block_number, self) + .await + { + Ok(Some(poi)) => Some(poi), + Ok(None) => None, + Err(e) => { + error!( + self.logger, + "Failed to query public proof of indexing"; + "subgraph" => &request.deployment, + "block" => format!("{}", request.block_number), + "error" => format!("{:?}", e) + ); + None + } + }; - public_poi_results.push( PublicProofOfIndexingResult { deployment: request.deployment, block: match poi_result { @@ -447,9 +448,11 @@ where }, proof_of_indexing: poi_result.map(|(_, poi)| poi), } - .into_value(), - ) - } + .into_value() + }) + .collect(); + + let public_poi_results = future::join_all(poi_futures).await; Ok(r::Value::List(public_poi_results)) }