@@ -62,10 +62,10 @@ enum ReconciliationStep<C>
62
62
where
63
63
C : Blockchain ,
64
64
{
65
- /// Revert the current block pointed at by the subgraph pointer. The pointer is to the current
65
+ /// Revert(from, to) the current block pointed at by the subgraph pointer. The pointer is to the current
66
66
/// subgraph head, and a single block will be reverted so the new head will be the parent of the
67
- /// current one.
68
- Revert ( BlockPtr ) ,
67
+ /// current one. The second BlockPtr is the parent.
68
+ Revert ( BlockPtr , BlockPtr ) ,
69
69
70
70
/// Move forwards, processing one or more blocks. Second element is the block range size.
71
71
ProcessDescendantBlocks ( Vec < BlockWithTriggers < C > > , BlockNumber ) ,
@@ -101,6 +101,7 @@ where
101
101
max_block_range_size : BlockNumber ,
102
102
target_triggers_per_block_range : u64 ,
103
103
unified_api_version : UnifiedMappingApiVersion ,
104
+ current_block : Option < BlockPtr > ,
104
105
}
105
106
106
107
impl < C : Blockchain > Clone for PollingBlockStreamContext < C > {
@@ -121,6 +122,7 @@ impl<C: Blockchain> Clone for PollingBlockStreamContext<C> {
121
122
max_block_range_size : self . max_block_range_size ,
122
123
target_triggers_per_block_range : self . target_triggers_per_block_range ,
123
124
unified_api_version : self . unified_api_version . clone ( ) ,
125
+ current_block : self . current_block . clone ( ) ,
124
126
}
125
127
}
126
128
}
@@ -140,9 +142,9 @@ where
140
142
/// Blocks and range size
141
143
Blocks ( VecDeque < BlockWithTriggers < C > > , BlockNumber ) ,
142
144
143
- // The payload is the current subgraph head pointer, which should be reverted, such that the
145
+ // The payload is the current subgraph head pointer, which should be reverted and it's parent , such that the
144
146
// parent of the current subgraph head becomes the new subgraph head.
145
- Revert ( BlockPtr ) ,
147
+ Revert ( BlockPtr , BlockPtr ) ,
146
148
Done ,
147
149
}
148
150
@@ -165,12 +167,14 @@ where
165
167
max_block_range_size : BlockNumber ,
166
168
target_triggers_per_block_range : u64 ,
167
169
unified_api_version : UnifiedMappingApiVersion ,
170
+ start_block : Option < BlockPtr > ,
168
171
) -> Self {
169
172
Self {
170
173
state : BlockStreamState :: BeginReconciliation ,
171
174
consecutive_err_count : 0 ,
172
175
chain_head_update_stream,
173
176
ctx : PollingBlockStreamContext {
177
+ current_block : start_block,
174
178
subgraph_store,
175
179
chain_store,
176
180
adapter,
@@ -216,7 +220,7 @@ where
216
220
217
221
return Ok ( NextBlocks :: Done ) ;
218
222
}
219
- ReconciliationStep :: Revert ( block ) => return Ok ( NextBlocks :: Revert ( block ) ) ,
223
+ ReconciliationStep :: Revert ( from , to ) => return Ok ( NextBlocks :: Revert ( from , to ) ) ,
220
224
}
221
225
}
222
226
}
@@ -229,7 +233,7 @@ where
229
233
230
234
// Get pointers from database for comparison
231
235
let head_ptr_opt = ctx. chain_store . chain_head_ptr ( ) ?;
232
- let subgraph_ptr = ctx . subgraph_store . block_ptr ( ) ? ;
236
+ let subgraph_ptr = self . current_block . clone ( ) ;
233
237
234
238
// If chain head ptr is not set yet
235
239
let head_ptr = match head_ptr_opt {
@@ -249,7 +253,7 @@ where
249
253
trace ! (
250
254
ctx. logger, "Subgraph pointer" ;
251
255
"hash" => format!( "{:?}" , subgraph_ptr. as_ref( ) . map( |block| & block. hash) ) ,
252
- "number" => subgraph_ptr. as_ref( ) . map( |block| block. number) ,
256
+ "number" => subgraph_ptr. as_ref( ) . map( |block| & block. number) ,
253
257
) ;
254
258
255
259
// Make sure not to include genesis in the reorg threshold.
@@ -317,7 +321,10 @@ where
317
321
//
318
322
// Note: We can safely unwrap the subgraph ptr here, because
319
323
// if it was `None`, `is_on_main_chain` would be true.
320
- return Ok ( ReconciliationStep :: Revert ( subgraph_ptr. unwrap ( ) ) ) ;
324
+ let from = subgraph_ptr. unwrap ( ) ;
325
+ let parent = self . parent_ptr ( & from) . await ?;
326
+
327
+ return Ok ( ReconciliationStep :: Revert ( from, parent) ) ;
321
328
}
322
329
323
330
// The subgraph ptr points to a block on the main chain.
@@ -422,7 +429,8 @@ where
422
429
423
430
#[ cfg( debug_assertions) ]
424
431
if test_reorg ( subgraph_ptr. clone ( ) ) {
425
- return Ok ( ReconciliationStep :: Revert ( subgraph_ptr) ) ;
432
+ let parent = self . parent_ptr ( & subgraph_ptr) . await ?;
433
+ return Ok ( ReconciliationStep :: Revert ( subgraph_ptr. clone ( ) , parent) ) ;
426
434
}
427
435
428
436
// Precondition: subgraph_ptr.number < head_ptr.number
@@ -457,16 +465,28 @@ where
457
465
. await ?;
458
466
Ok ( ReconciliationStep :: ProcessDescendantBlocks ( vec ! [ block] , 1 ) )
459
467
} else {
468
+ let parent = self . parent_ptr ( & subgraph_ptr) . await ?;
469
+
460
470
// The subgraph ptr is not on the main chain.
461
471
// We will need to step back (possibly repeatedly) one block at a time
462
472
// until we are back on the main chain.
463
- Ok ( ReconciliationStep :: Revert ( subgraph_ptr) )
473
+ Ok ( ReconciliationStep :: Revert ( subgraph_ptr, parent ) )
464
474
}
465
475
}
466
476
}
467
477
}
468
478
}
469
479
480
+ async fn parent_ptr ( & self , block_ptr : & BlockPtr ) -> Result < BlockPtr , Error > {
481
+ let ptr = self
482
+ . adapter
483
+ . parent_ptr ( block_ptr)
484
+ . await ?
485
+ . expect ( "genesis block can't be reverted" ) ;
486
+
487
+ Ok ( ptr)
488
+ }
489
+
470
490
/// Set subgraph deployment entity synced flag if and only if the subgraph block pointer is
471
491
/// caught up to the head block pointer.
472
492
fn update_subgraph_synced_status ( & self ) -> Result < ( ) , StoreError > {
@@ -505,54 +525,60 @@ impl<C: Blockchain> Stream for PollingBlockStream<C> {
505
525
// Waiting for the reconciliation to complete or yield blocks
506
526
BlockStreamState :: Reconciliation ( next_blocks_future) => {
507
527
match next_blocks_future. poll_unpin ( cx) {
508
- Poll :: Ready ( Ok ( NextBlocks :: Blocks ( next_blocks, block_range_size) ) ) => {
509
- // We had only one error, so we infer that reducing the range size is
510
- // what fixed it. Reduce the max range size to prevent future errors.
511
- // See: 018c6df4-132f-4acc-8697-a2d64e83a9f0
512
- if self . consecutive_err_count == 1 {
513
- // Reduce the max range size by 10%, but to no less than 10.
514
- self . ctx . max_block_range_size =
515
- ( self . ctx . max_block_range_size * 9 / 10 ) . max ( 10 ) ;
528
+ Poll :: Ready ( Ok ( next_block_step) ) => match next_block_step {
529
+ NextBlocks :: Blocks ( next_blocks, block_range_size) => {
530
+ // We had only one error, so we infer that reducing the range size is
531
+ // what fixed it. Reduce the max range size to prevent future errors.
532
+ // See: 018c6df4-132f-4acc-8697-a2d64e83a9f0
533
+ if self . consecutive_err_count == 1 {
534
+ // Reduce the max range size by 10%, but to no less than 10.
535
+ self . ctx . max_block_range_size =
536
+ ( self . ctx . max_block_range_size * 9 / 10 ) . max ( 10 ) ;
537
+ }
538
+ self . consecutive_err_count = 0 ;
539
+
540
+ let total_triggers =
541
+ next_blocks. iter ( ) . map ( |b| b. trigger_count ( ) ) . sum :: < usize > ( ) ;
542
+ self . ctx . previous_triggers_per_block =
543
+ total_triggers as f64 / block_range_size as f64 ;
544
+ self . ctx . previous_block_range_size = block_range_size;
545
+ if total_triggers > 0 {
546
+ debug ! (
547
+ self . ctx. logger,
548
+ "Processing {} triggers" , total_triggers
549
+ ) ;
550
+ }
551
+
552
+ // Switch to yielding state until next_blocks is depleted
553
+ self . state =
554
+ BlockStreamState :: YieldingBlocks ( Box :: new ( next_blocks) ) ;
555
+
556
+ // Yield the first block in next_blocks
557
+ continue ;
516
558
}
517
- self . consecutive_err_count = 0 ;
518
-
519
- let total_triggers =
520
- next_blocks. iter ( ) . map ( |b| b. trigger_count ( ) ) . sum :: < usize > ( ) ;
521
- self . ctx . previous_triggers_per_block =
522
- total_triggers as f64 / block_range_size as f64 ;
523
- self . ctx . previous_block_range_size = block_range_size;
524
- if total_triggers > 0 {
525
- debug ! ( self . ctx. logger, "Processing {} triggers" , total_triggers) ;
526
- }
527
-
528
- // Switch to yielding state until next_blocks is depleted
529
- self . state = BlockStreamState :: YieldingBlocks ( Box :: new ( next_blocks) ) ;
530
-
531
- // Yield the first block in next_blocks
532
- continue ;
533
- }
534
- // Reconciliation completed. We're caught up to chain head.
535
- Poll :: Ready ( Ok ( NextBlocks :: Done ) ) => {
536
- // Reset error count
537
- self . consecutive_err_count = 0 ;
559
+ // Reconciliation completed. We're caught up to chain head.
560
+ NextBlocks :: Done => {
561
+ // Reset error count
562
+ self . consecutive_err_count = 0 ;
538
563
539
- // Switch to idle
540
- self . state = BlockStreamState :: Idle ;
564
+ // Switch to idle
565
+ self . state = BlockStreamState :: Idle ;
541
566
542
- // Poll for chain head update
543
- continue ;
544
- }
545
- Poll :: Ready ( Ok ( NextBlocks :: Revert ( block) ) ) => {
546
- self . state = BlockStreamState :: BeginReconciliation ;
547
- break Poll :: Ready ( Some ( Ok ( BlockStreamEvent :: Revert (
548
- block,
549
- FirehoseCursor :: None ,
550
- None ,
551
- ) ) ) ) ;
552
- }
553
- Poll :: Pending => {
554
- break Poll :: Pending ;
555
- }
567
+ // Poll for chain head update
568
+ continue ;
569
+ }
570
+ NextBlocks :: Revert ( from, to) => {
571
+ self . ctx . current_block = to. into ( ) ;
572
+
573
+ self . state = BlockStreamState :: BeginReconciliation ;
574
+ break Poll :: Ready ( Some ( Ok ( BlockStreamEvent :: Revert (
575
+ from,
576
+ FirehoseCursor :: None ,
577
+ self . ctx . current_block . clone ( ) ,
578
+ ) ) ) ) ;
579
+ }
580
+ } ,
581
+ Poll :: Pending => break Poll :: Pending ,
556
582
Poll :: Ready ( Err ( e) ) => {
557
583
// Reset the block range size in an attempt to recover from the error.
558
584
// See also: 018c6df4-132f-4acc-8697-a2d64e83a9f0
@@ -577,6 +603,8 @@ impl<C: Blockchain> Stream for PollingBlockStream<C> {
577
603
match next_blocks. pop_front ( ) {
578
604
// Yield one block
579
605
Some ( next_block) => {
606
+ self . ctx . current_block = Some ( next_block. block . ptr ( ) ) ;
607
+
580
608
break Poll :: Ready ( Some ( Ok ( BlockStreamEvent :: ProcessBlock (
581
609
next_block,
582
610
FirehoseCursor :: None ,
0 commit comments