@@ -7,7 +7,7 @@ use anyhow::Error;
77use async_stream:: stream;
88use futures03:: Stream ;
99use prost_types:: Any ;
10- use std:: collections:: { BTreeMap , HashMap , HashSet } ;
10+ use std:: collections:: { BTreeMap , BTreeSet , HashMap } ;
1111use std:: fmt;
1212use std:: sync:: Arc ;
1313use std:: time:: Instant ;
@@ -339,53 +339,127 @@ impl<C: Blockchain> TriggersAdapterWrapper<C> {
339339 pub async fn blocks_with_subgraph_triggers (
340340 & self ,
341341 logger : & Logger ,
342- subgraph_filter : & SubgraphFilter ,
342+ filters : & [ SubgraphFilter ] ,
343343 range : SubgraphTriggerScanRange < C > ,
344344 ) -> Result < Vec < BlockWithTriggers < C > > , Error > {
345- let store = self
346- . source_subgraph_stores
347- . get ( & subgraph_filter. subgraph )
348- . ok_or_else ( || anyhow ! ( "Store not found for subgraph: {}" , subgraph_filter. subgraph) ) ?;
345+ if filters. is_empty ( ) {
346+ return Err ( anyhow ! ( "No subgraph filters provided" ) ) ;
347+ }
348+
349+ let ( blocks, hash_to_entities) = match range {
350+ SubgraphTriggerScanRange :: Single ( block) => {
351+ let hash_to_entities = self
352+ . fetch_entities_for_filters ( filters, block. number ( ) , block. number ( ) )
353+ . await ?;
354+
355+ ( vec ! [ block] , hash_to_entities)
356+ }
357+ SubgraphTriggerScanRange :: Range ( from, to) => {
358+ let hash_to_entities = self . fetch_entities_for_filters ( filters, from, to) . await ?;
359+
360+ // Get block numbers that have entities
361+ let mut block_numbers: BTreeSet < _ > = hash_to_entities
362+ . iter ( )
363+ . flat_map ( |( _, entities, _) | entities. keys ( ) . copied ( ) )
364+ . collect ( ) ;
365+
366+ // Always include the last block in the range
367+ block_numbers. insert ( to) ;
368+
369+ let blocks = self
370+ . adapter
371+ . load_block_ptrs_by_numbers ( logger. clone ( ) , block_numbers)
372+ . await ?;
349373
350- let schema = <dyn crate :: components:: store:: SourceableStore >:: input_schema ( store) ;
374+ ( blocks, hash_to_entities)
375+ }
376+ } ;
351377
352- let adapter = self . adapter . clone ( ) ;
378+ create_subgraph_triggers :: < C > ( logger. clone ( ) , blocks, hash_to_entities) . await
379+ }
380+
381+ async fn fetch_entities_for_filters (
382+ & self ,
383+ filters : & [ SubgraphFilter ] ,
384+ from : BlockNumber ,
385+ to : BlockNumber ,
386+ ) -> Result <
387+ Vec < (
388+ DeploymentHash ,
389+ BTreeMap < BlockNumber , Vec < EntitySourceOperation > > ,
390+ u32 ,
391+ ) > ,
392+ Error ,
393+ > {
394+ let futures = filters
395+ . iter ( )
396+ . filter_map ( |filter| {
397+ self . source_subgraph_stores
398+ . get ( & filter. subgraph )
399+ . map ( |store| {
400+ let store = store. clone ( ) ;
401+ let schema = store. input_schema ( ) ;
402+
403+ async move {
404+ let entities =
405+ get_entities_for_range ( & store, filter, & schema, from, to) . await ?;
406+ Ok :: < _ , Error > ( ( filter. subgraph . clone ( ) , entities, filter. manifest_idx ) )
407+ }
408+ } )
409+ } )
410+ . collect :: < Vec < _ > > ( ) ;
411+
412+ if futures. is_empty ( ) {
413+ return Ok ( Vec :: new ( ) ) ;
414+ }
353415
354- scan_subgraph_triggers :: < C > ( logger , store , & adapter , & schema , & subgraph_filter , range ) . await
416+ futures03 :: future :: try_join_all ( futures ) . await
355417 }
356418}
357419
358420fn create_subgraph_trigger_from_entities (
359- filter : & SubgraphFilter ,
421+ subgraph : & DeploymentHash ,
360422 entities : Vec < EntitySourceOperation > ,
423+ manifest_idx : u32 ,
361424) -> Vec < subgraph:: TriggerData > {
362425 entities
363426 . into_iter ( )
364427 . map ( |entity| subgraph:: TriggerData {
365- source : filter . subgraph . clone ( ) ,
428+ source : subgraph. clone ( ) ,
366429 entity,
430+ source_idx : manifest_idx,
367431 } )
368432 . collect ( )
369433}
370434
371435async fn create_subgraph_triggers < C : Blockchain > (
372436 logger : Logger ,
373437 blocks : Vec < C :: Block > ,
374- filter : & SubgraphFilter ,
375- mut entities : BTreeMap < BlockNumber , Vec < EntitySourceOperation > > ,
438+ subgraph_data : Vec < (
439+ DeploymentHash ,
440+ BTreeMap < BlockNumber , Vec < EntitySourceOperation > > ,
441+ u32 ,
442+ ) > ,
376443) -> Result < Vec < BlockWithTriggers < C > > , Error > {
377444 let logger_clone = logger. cheap_clone ( ) ;
378-
379445 let blocks: Vec < BlockWithTriggers < C > > = blocks
380446 . into_iter ( )
381447 . map ( |block| {
382448 let block_number = block. number ( ) ;
383- let trigger_data = entities
384- . remove ( & block_number)
385- . map ( |e| create_subgraph_trigger_from_entities ( filter, e) )
386- . unwrap_or_else ( Vec :: new) ;
449+ let mut all_trigger_data = Vec :: new ( ) ;
450+
451+ for ( hash, entities, manifest_idx) in subgraph_data. iter ( ) {
452+ if let Some ( block_entities) = entities. get ( & block_number) {
453+ let trigger_data = create_subgraph_trigger_from_entities (
454+ hash,
455+ block_entities. clone ( ) ,
456+ * manifest_idx,
457+ ) ;
458+ all_trigger_data. extend ( trigger_data) ;
459+ }
460+ }
387461
388- BlockWithTriggers :: new_with_subgraph_triggers ( block, trigger_data , & logger_clone)
462+ BlockWithTriggers :: new_with_subgraph_triggers ( block, all_trigger_data , & logger_clone)
389463 } )
390464 . collect ( ) ;
391465
@@ -397,36 +471,6 @@ pub enum SubgraphTriggerScanRange<C: Blockchain> {
397471 Range ( BlockNumber , BlockNumber ) ,
398472}
399473
400- async fn scan_subgraph_triggers < C : Blockchain > (
401- logger : & Logger ,
402- store : & Arc < dyn SourceableStore > ,
403- adapter : & Arc < dyn TriggersAdapter < C > > ,
404- schema : & InputSchema ,
405- filter : & SubgraphFilter ,
406- range : SubgraphTriggerScanRange < C > ,
407- ) -> Result < Vec < BlockWithTriggers < C > > , Error > {
408- match range {
409- SubgraphTriggerScanRange :: Single ( block) => {
410- let entities =
411- get_entities_for_range ( store, filter, schema, block. number ( ) , block. number ( ) )
412- . await ?;
413- create_subgraph_triggers :: < C > ( logger. clone ( ) , vec ! [ block] , filter, entities) . await
414- }
415- SubgraphTriggerScanRange :: Range ( from, to) => {
416- let entities = get_entities_for_range ( store, filter, schema, from, to) . await ?;
417- let mut block_numbers: HashSet < BlockNumber > = entities. keys ( ) . cloned ( ) . collect ( ) ;
418- // Ensure the 'to' block is included in the block_numbers
419- block_numbers. insert ( to) ;
420-
421- let blocks = adapter
422- . load_block_ptrs_by_numbers ( logger. clone ( ) , block_numbers)
423- . await ?;
424-
425- create_subgraph_triggers :: < C > ( logger. clone ( ) , blocks, filter, entities) . await
426- }
427- }
428- }
429-
430474#[ derive( Debug , Clone , Eq , PartialEq ) ]
431475pub enum EntityOperationKind {
432476 Create ,
@@ -474,11 +518,11 @@ impl<C: Blockchain> TriggersAdapterWrapper<C> {
474518 to : BlockNumber ,
475519 filter : & Arc < TriggerFilterWrapper < C > > ,
476520 ) -> Result < ( Vec < BlockWithTriggers < C > > , BlockNumber ) , Error > {
477- if let Some ( subgraph_filter ) = filter. subgraph_filter . first ( ) {
521+ if ! filter. subgraph_filter . is_empty ( ) {
478522 let blocks_with_triggers = self
479523 . blocks_with_subgraph_triggers (
480524 logger,
481- subgraph_filter,
525+ & filter . subgraph_filter ,
482526 SubgraphTriggerScanRange :: Range ( from, to) ,
483527 )
484528 . await ?;
@@ -504,11 +548,11 @@ impl<C: Blockchain> TriggersAdapterWrapper<C> {
504548 "block_hash" => block. hash( ) . hash_hex( ) ,
505549 ) ;
506550
507- if let Some ( subgraph_filter ) = filter. subgraph_filter . first ( ) {
551+ if ! filter. subgraph_filter . is_empty ( ) {
508552 let blocks_with_triggers = self
509553 . blocks_with_subgraph_triggers (
510554 logger,
511- subgraph_filter,
555+ & filter . subgraph_filter ,
512556 SubgraphTriggerScanRange :: Single ( block) ,
513557 )
514558 . await ?;
@@ -594,7 +638,7 @@ pub trait TriggersAdapter<C: Blockchain>: Send + Sync {
594638 async fn load_block_ptrs_by_numbers (
595639 & self ,
596640 logger : Logger ,
597- block_numbers : HashSet < BlockNumber > ,
641+ block_numbers : BTreeSet < BlockNumber > ,
598642 ) -> Result < Vec < C :: Block > > ;
599643}
600644
0 commit comments