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

Subgraph composition : TriggersAdapter wrapper #5695

Open
wants to merge 21 commits into
base: feat-subgraph-composition
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3fe298e
graph: Add support for subgraph datasource in manifest
incrypto32 Jul 11, 2024
a45daf3
graph: wrap TriggerFilter with TriggerFilterWrapper
incrypto32 Jul 12, 2024
af3468c
graph,chain: add build_subgraph_block_stream method
incrypto32 Jul 12, 2024
d59c14b
graph,core,chain: use TriggerFilterWrapper in PollingBlockStream
incrypto32 Jul 15, 2024
edc806c
graph: created TriggersAdapterWrapper
incrypto32 Jul 15, 2024
eb41c6b
graph,core,chain: Add a wrapper enum for Triggers to handle subgraph …
incrypto32 Jul 16, 2024
3710cf8
graph, chain: Build subgraph trigger filters in build_filter
incrypto32 Jul 16, 2024
579d886
graph,core: Add subgraph_hosts to RuntimeHostBuilder
incrypto32 Jul 17, 2024
cb4d082
chain, core, graph: Add source_subgraph_stores to indexing inputs
incrypto32 Jul 18, 2024
ff572cf
graph, chain: minor refactoring and formatting
incrypto32 Jul 18, 2024
35b2a54
graph, chain: fix typo in TriggersAdapterWrapper
incrypto32 Jul 18, 2024
fe5d5ba
chain, graph: use TriggerFilterWrapper in scan_triggers
incrypto32 Jul 18, 2024
4c05119
chain/ethereum: implement load_blocks_by_numbers for EthereumAdapter
incrypto32 Jul 24, 2024
d20bafd
graph: refactor BlockWithTriggers impl
incrypto32 Jul 24, 2024
3ab4941
graph, core: Add a new SubgraphFilter struct
incrypto32 Jul 24, 2024
aec82dc
chain/ethereum: Mock implementation of subgraph_triggers for ethereum
incrypto32 Jul 24, 2024
ae7559d
chain,graph : use `chain_head_ptr` method from adapter
incrypto32 Jul 24, 2024
686e7e1
chain, core, graph : use TriggersAdapterWrapper at top level
incrypto32 Jul 25, 2024
3aba98f
chain, graph : move subgraph trigger scanning back to TriggersAdapter…
incrypto32 Jul 25, 2024
9069486
graph: use ReadStore instead of WriteStore for source subgraph stores
incrypto32 Nov 12, 2024
c7ca25a
graph: Better comments
incrypto32 Nov 12, 2024
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
28 changes: 23 additions & 5 deletions chain/arweave/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ use graph::blockchain::client::ChainClient;
use graph::blockchain::firehose_block_ingestor::FirehoseBlockIngestor;
use graph::blockchain::{
BasicBlockchainBuilder, Block, BlockIngestor, BlockchainBuilder, BlockchainKind,
EmptyNodeCapabilities, NoopDecoderHook, NoopRuntimeAdapter,
EmptyNodeCapabilities, NoopDecoderHook, NoopRuntimeAdapter, TriggerFilterWrapper,
};
use graph::cheap_clone::CheapClone;
use graph::components::adapter::ChainId;
use graph::components::store::DeploymentCursorTracker;
use graph::components::store::{DeploymentCursorTracker, ReadStore};
use graph::data::subgraph::UnifiedMappingApiVersion;
use graph::env::EnvVars;
use graph::firehose::FirehoseEndpoint;
use graph::prelude::MetricsRegistry;
use graph::prelude::{DeploymentHash, MetricsRegistry};
use graph::substreams::Clock;
use graph::{
blockchain::{
Expand All @@ -27,11 +27,13 @@ use graph::{
prelude::{async_trait, o, BlockNumber, ChainStore, Error, Logger, LoggerFactory},
};
use prost::Message;
use std::collections::HashSet;
use std::sync::Arc;

use crate::adapter::TriggerFilter;
use crate::data_source::{DataSourceTemplate, UnresolvedDataSourceTemplate};
use crate::trigger::{self, ArweaveTrigger};
use crate::Block as ArweaveBlock;
use crate::{
codec,
data_source::{DataSource, UnresolvedDataSource},
Expand Down Expand Up @@ -119,7 +121,8 @@ impl Blockchain for Chain {
deployment: DeploymentLocator,
store: impl DeploymentCursorTracker,
start_blocks: Vec<BlockNumber>,
filter: Arc<Self::TriggerFilter>,
_source_subgraph_stores: Vec<(DeploymentHash, Arc<dyn ReadStore>)>,
filter: Arc<TriggerFilterWrapper<Self>>,
unified_api_version: UnifiedMappingApiVersion,
) -> Result<Box<dyn BlockStream<Self>>, Error> {
let adapter = self
Expand All @@ -135,7 +138,10 @@ impl Blockchain for Chain {
.subgraph_logger(&deployment)
.new(o!("component" => "FirehoseBlockStream"));

let firehose_mapper = Arc::new(FirehoseMapper { adapter, filter });
let firehose_mapper = Arc::new(FirehoseMapper {
adapter,
filter: filter.chain_filter.clone(),
});

Ok(Box::new(FirehoseBlockStream::new(
deployment.hash,
Expand Down Expand Up @@ -199,6 +205,10 @@ impl TriggersAdapterTrait<Chain> for TriggersAdapter {
panic!("Should never be called since not used by FirehoseBlockStream")
}

async fn chain_head_ptr(&self) -> Result<Option<BlockPtr>, Error> {
unimplemented!()
}

async fn triggers_in_block(
&self,
logger: &Logger,
Expand Down Expand Up @@ -258,6 +268,14 @@ impl TriggersAdapterTrait<Chain> for TriggersAdapter {
number: block.number.saturating_sub(1),
}))
}

async fn load_blocks_by_numbers(
&self,
_logger: Logger,
_block_numbers: HashSet<BlockNumber>,
) -> Result<Vec<ArweaveBlock>, Error> {
todo!()
}
}

pub struct FirehoseMapper {
Expand Down
43 changes: 33 additions & 10 deletions chain/cosmos/src/chain.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use graph::blockchain::firehose_block_ingestor::FirehoseBlockIngestor;
use graph::blockchain::{BlockIngestor, NoopDecoderHook};
use graph::blockchain::{BlockIngestor, NoopDecoderHook, TriggerFilterWrapper};
use graph::components::adapter::ChainId;
use graph::env::EnvVars;
use graph::prelude::MetricsRegistry;
use graph::prelude::{DeploymentHash, MetricsRegistry};
use graph::substreams::Clock;
use std::collections::HashSet;
use std::convert::TryFrom;
use std::sync::Arc;

use graph::blockchain::block_stream::{BlockStreamError, BlockStreamMapper, FirehoseCursor};
use graph::blockchain::client::ChainClient;
use graph::blockchain::{BasicBlockchainBuilder, BlockchainBuilder, NoopRuntimeAdapter};
use graph::cheap_clone::CheapClone;
use graph::components::store::DeploymentCursorTracker;
use graph::components::store::{DeploymentCursorTracker, ReadStore};
use graph::data::subgraph::UnifiedMappingApiVersion;
use graph::{
blockchain::{
Expand All @@ -33,7 +34,7 @@ use crate::data_source::{
DataSource, DataSourceTemplate, EventOrigin, UnresolvedDataSource, UnresolvedDataSourceTemplate,
};
use crate::trigger::CosmosTrigger;
use crate::{codec, TriggerFilter};
use crate::{codec, Block, TriggerFilter};

pub struct Chain {
logger_factory: LoggerFactory,
Expand Down Expand Up @@ -113,7 +114,8 @@ impl Blockchain for Chain {
deployment: DeploymentLocator,
store: impl DeploymentCursorTracker,
start_blocks: Vec<BlockNumber>,
filter: Arc<Self::TriggerFilter>,
_source_subgraph_stores: Vec<(DeploymentHash, Arc<dyn ReadStore>)>,
filter: Arc<TriggerFilterWrapper<Self>>,
unified_api_version: UnifiedMappingApiVersion,
) -> Result<Box<dyn BlockStream<Self>>, Error> {
let adapter = self
Expand All @@ -129,7 +131,10 @@ impl Blockchain for Chain {
.subgraph_logger(&deployment)
.new(o!("component" => "FirehoseBlockStream"));

let firehose_mapper = Arc::new(FirehoseMapper { adapter, filter });
let firehose_mapper = Arc::new(FirehoseMapper {
adapter,
filter: filter.chain_filter.clone(),
});

Ok(Box::new(FirehoseBlockStream::new(
deployment.hash,
Expand Down Expand Up @@ -193,6 +198,18 @@ impl TriggersAdapterTrait<Chain> for TriggersAdapter {
panic!("Should never be called since not used by FirehoseBlockStream")
}

async fn load_blocks_by_numbers(
&self,
_logger: Logger,
_block_numbers: HashSet<BlockNumber>,
) -> Result<Vec<Block>, Error> {
unimplemented!()
}

async fn chain_head_ptr(&self) -> Result<Option<BlockPtr>, Error> {
unimplemented!()
}

async fn scan_triggers(
&self,
_from: BlockNumber,
Expand Down Expand Up @@ -467,9 +484,12 @@ impl FirehoseMapperTrait<Chain> for FirehoseMapper {

#[cfg(test)]
mod test {
use graph::prelude::{
slog::{o, Discard, Logger},
tokio,
use graph::{
blockchain::Trigger,
prelude::{
slog::{o, Discard, Logger},
tokio,
},
};

use super::*;
Expand Down Expand Up @@ -600,7 +620,10 @@ mod test {
// they may not be in the same order
for trigger in expected_triggers {
assert!(
triggers.trigger_data.contains(&trigger),
triggers.trigger_data.iter().any(|t| match t {
Trigger::Chain(t) => t == &trigger,
_ => false,
}),
"Expected trigger list to contain {:?}, but it only contains: {:?}",
trigger,
triggers.trigger_data
Expand Down
7 changes: 7 additions & 0 deletions chain/ethereum/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,13 @@ pub trait EthereumAdapter: Send + Sync + 'static {
block_hash: H256,
) -> Box<dyn Future<Item = LightEthereumBlock, Error = Error> + Send>;

async fn load_blocks_by_numbers(
&self,
_logger: Logger,
_chain_store: Arc<dyn ChainStore>,
_block_numbers: HashSet<BlockNumber>,
) -> Box<dyn Stream<Item = Arc<LightEthereumBlock>, Error = Error> + Send>;

/// Load Ethereum blocks in bulk, returning results as they come back as a Stream.
/// May use the `chain_store` as a cache.
async fn load_blocks(
Expand Down
107 changes: 91 additions & 16 deletions chain/ethereum/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ use anyhow::{Context, Error};
use graph::blockchain::client::ChainClient;
use graph::blockchain::firehose_block_ingestor::{FirehoseBlockIngestor, Transforms};
use graph::blockchain::{
BlockIngestor, BlockTime, BlockchainKind, ChainIdentifier, TriggersAdapterSelector,
BlockIngestor, BlockTime, BlockchainKind, ChainIdentifier, TriggerFilterWrapper,
TriggersAdapterSelector,
};
use graph::components::adapter::ChainId;
use graph::components::store::DeploymentCursorTracker;
use graph::components::store::{DeploymentCursorTracker, ReadStore};
use graph::data::subgraph::UnifiedMappingApiVersion;
use graph::firehose::{FirehoseEndpoint, ForkStep};
use graph::futures03::compat::Future01CompatExt;
use graph::prelude::{
BlockHash, ComponentLoggerConfig, ElasticComponentLoggerConfig, EthereumBlock,
BlockHash, ComponentLoggerConfig, DeploymentHash, ElasticComponentLoggerConfig, EthereumBlock,
EthereumCallCache, LightEthereumBlock, LightEthereumBlockExt, MetricsRegistry,
};
use graph::schema::InputSchema;
Expand Down Expand Up @@ -61,6 +62,7 @@ use crate::{BufferedCallCache, NodeCapabilities};
use crate::{EthereumAdapter, RuntimeAdapter};
use graph::blockchain::block_stream::{
BlockStream, BlockStreamBuilder, BlockStreamError, BlockStreamMapper, FirehoseCursor,
TriggersAdapterWrapper,
};

/// Celo Mainnet: 42220, Testnet Alfajores: 44787, Testnet Baklava: 62320
Expand Down Expand Up @@ -121,24 +123,50 @@ impl BlockStreamBuilder<Chain> for EthereumStreamBuilder {
unimplemented!()
}

async fn build_subgraph_block_stream(
&self,
chain: &Chain,
deployment: DeploymentLocator,
start_blocks: Vec<BlockNumber>,
source_subgraph_stores: Vec<(DeploymentHash, Arc<dyn ReadStore>)>,
subgraph_current_block: Option<BlockPtr>,
filter: Arc<TriggerFilterWrapper<Chain>>,
unified_api_version: UnifiedMappingApiVersion,
) -> Result<Box<dyn BlockStream<Chain>>> {
self.build_polling(
chain,
deployment,
start_blocks,
source_subgraph_stores,
subgraph_current_block,
filter,
unified_api_version,
)
.await
}

async fn build_polling(
&self,
chain: &Chain,
deployment: DeploymentLocator,
start_blocks: Vec<BlockNumber>,
source_subgraph_stores: Vec<(DeploymentHash, Arc<dyn ReadStore>)>,
subgraph_current_block: Option<BlockPtr>,
filter: Arc<<Chain as Blockchain>::TriggerFilter>,
filter: Arc<TriggerFilterWrapper<Chain>>,
unified_api_version: UnifiedMappingApiVersion,
) -> Result<Box<dyn BlockStream<Chain>>> {
let requirements = filter.node_capabilities();
let adapter = chain
.triggers_adapter(&deployment, &requirements, unified_api_version.clone())
.unwrap_or_else(|_| {
panic!(
"no adapter for network {} with capabilities {}",
chain.name, requirements
)
});
let requirements = filter.chain_filter.node_capabilities();
let adapter = TriggersAdapterWrapper::new(
chain
.triggers_adapter(&deployment, &requirements, unified_api_version.clone())
.unwrap_or_else(|_| {
panic!(
"no adapter for network {} with capabilities {}",
chain.name, requirements
)
}),
source_subgraph_stores,
);

let logger = chain
.logger_factory
Expand Down Expand Up @@ -172,7 +200,7 @@ impl BlockStreamBuilder<Chain> for EthereumStreamBuilder {
Ok(Box::new(PollingBlockStream::new(
chain_store,
chain_head_update_stream,
adapter,
Arc::new(adapter),
chain.node_id.clone(),
deployment.hash,
filter,
Expand Down Expand Up @@ -409,17 +437,35 @@ impl Blockchain for Chain {
deployment: DeploymentLocator,
store: impl DeploymentCursorTracker,
start_blocks: Vec<BlockNumber>,
filter: Arc<Self::TriggerFilter>,
source_subgraph_stores: Vec<(DeploymentHash, Arc<dyn ReadStore>)>,
filter: Arc<TriggerFilterWrapper<Self>>,
unified_api_version: UnifiedMappingApiVersion,
) -> Result<Box<dyn BlockStream<Self>>, Error> {
let current_ptr = store.block_ptr();

if !filter.subgraph_filter.is_empty() {
return self
.block_stream_builder
.build_subgraph_block_stream(
self,
deployment,
start_blocks,
source_subgraph_stores,
current_ptr,
filter,
unified_api_version,
)
.await;
}

match self.chain_client().as_ref() {
ChainClient::Rpc(_) => {
self.block_stream_builder
.build_polling(
self,
deployment,
start_blocks,
source_subgraph_stores,
current_ptr,
filter,
unified_api_version,
Expand All @@ -434,7 +480,7 @@ impl Blockchain for Chain {
store.firehose_cursor(),
start_blocks,
current_ptr,
filter,
filter.chain_filter.clone(),
unified_api_version,
)
.await
Expand Down Expand Up @@ -689,6 +735,35 @@ impl TriggersAdapterTrait<Chain> for TriggersAdapter {
.await
}

async fn load_blocks_by_numbers(
&self,
logger: Logger,
block_numbers: HashSet<BlockNumber>,
) -> Result<Vec<BlockFinality>> {
use graph::futures01::stream::Stream;

let adapter = self
.chain_client
.rpc()?
.cheapest_with(&self.capabilities)
.await?;

let blocks = adapter
.load_blocks_by_numbers(logger, self.chain_store.clone(), block_numbers)
.await
.map(|block| BlockFinality::Final(block))
.collect()
.compat()
.await?;

Ok(blocks)
}

async fn chain_head_ptr(&self) -> Result<Option<BlockPtr>, Error> {
let chain_store = self.chain_store.clone();
chain_store.chain_head_ptr().await
}

async fn triggers_in_block(
&self,
logger: &Logger,
Expand Down
Loading
Loading