@@ -5,13 +5,15 @@ use std::{collections::BTreeMap, sync::Arc};
5
5
6
6
use graph:: blockchain:: block_stream:: FirehoseCursor ;
7
7
use graph:: components:: store:: { DeploymentCursorTracker , DerivedEntityQuery , EntityKey , ReadStore } ;
8
+ use graph:: constraint_violation;
8
9
use graph:: data:: subgraph:: schema;
9
10
use graph:: data_source:: CausalityRegion ;
10
11
use graph:: prelude:: {
11
12
BlockNumber , Entity , MetricsRegistry , Schema , SubgraphDeploymentEntity , SubgraphStore as _,
12
13
BLOCK_NUMBER_MAX ,
13
14
} ;
14
15
use graph:: slog:: info;
16
+ use graph:: tokio:: task:: JoinHandle ;
15
17
use graph:: util:: bounded_queue:: BoundedQueue ;
16
18
use graph:: {
17
19
cheap_clone:: CheapClone ,
@@ -448,6 +450,29 @@ enum Request {
448
450
Stop ,
449
451
}
450
452
453
+ impl std:: fmt:: Debug for Request {
454
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
455
+ match self {
456
+ Self :: Write {
457
+ block_ptr,
458
+ mods,
459
+ store,
460
+ ..
461
+ } => write ! (
462
+ f,
463
+ "write[{}, {:p}, {} entities]" ,
464
+ block_ptr. number,
465
+ store. as_ref( ) ,
466
+ mods. len( )
467
+ ) ,
468
+ Self :: RevertTo {
469
+ block_ptr, store, ..
470
+ } => write ! ( f, "revert[{}, {:p}]" , block_ptr. number, store. as_ref( ) ) ,
471
+ Self :: Stop => write ! ( f, "stop" ) ,
472
+ }
473
+ }
474
+ }
475
+
451
476
enum ExecResult {
452
477
Continue ,
453
478
Stop ,
@@ -520,28 +545,56 @@ struct Queue {
520
545
/// allowed to process as many requests as it can
521
546
#[ cfg( debug_assertions) ]
522
547
pub ( crate ) mod test_support {
523
- use std:: sync:: atomic:: { AtomicBool , Ordering } ;
548
+ use std:: {
549
+ collections:: HashMap ,
550
+ sync:: { Arc , Mutex } ,
551
+ } ;
524
552
525
- use graph:: { prelude:: lazy_static, util:: bounded_queue:: BoundedQueue } ;
553
+ use graph:: {
554
+ components:: store:: { DeploymentId , DeploymentLocator } ,
555
+ prelude:: lazy_static,
556
+ util:: bounded_queue:: BoundedQueue ,
557
+ } ;
526
558
527
559
lazy_static ! {
528
- static ref DO_STEP : AtomicBool = AtomicBool :: new ( false ) ;
529
- static ref ALLOWED_STEPS : BoundedQueue < ( ) > = BoundedQueue :: with_capacity ( 1_000 ) ;
560
+ static ref STEPS : Mutex < HashMap < DeploymentId , Arc < BoundedQueue < ( ) >>>> =
561
+ Mutex :: new ( HashMap :: new ( ) ) ;
530
562
}
531
563
532
- pub ( super ) async fn take_step ( ) {
533
- if DO_STEP . load ( Ordering :: SeqCst ) {
534
- ALLOWED_STEPS . pop ( ) . await
564
+ pub ( super ) async fn take_step ( deployment : & DeploymentLocator ) {
565
+ let steps = STEPS . lock ( ) . unwrap ( ) . get ( & deployment. id ) . cloned ( ) ;
566
+ if let Some ( steps) = steps {
567
+ steps. pop ( ) . await ;
535
568
}
536
569
}
537
570
538
571
/// Allow the writer to process `steps` requests. After calling this,
539
572
/// the writer will only process the number of requests it is allowed to
540
- pub async fn allow_steps ( steps : usize ) {
573
+ pub async fn allow_steps ( deployment : & DeploymentLocator , steps : usize ) {
574
+ let queue = {
575
+ let mut map = STEPS . lock ( ) . unwrap ( ) ;
576
+ map. entry ( deployment. id )
577
+ . or_insert_with ( || Arc :: new ( BoundedQueue :: with_capacity ( 1_000 ) ) )
578
+ . clone ( )
579
+ } ;
541
580
for _ in 0 ..steps {
542
- ALLOWED_STEPS . push ( ( ) ) . await
581
+ queue . push ( ( ) ) . await
543
582
}
544
- DO_STEP . store ( true , Ordering :: SeqCst ) ;
583
+ }
584
+ }
585
+
586
+ impl std:: fmt:: Debug for Queue {
587
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
588
+ let reqs = self . queue . fold ( vec ! [ ] , |mut reqs, req| {
589
+ reqs. push ( req. clone ( ) ) ;
590
+ reqs
591
+ } ) ;
592
+
593
+ write ! ( f, "reqs[{} : " , self . store. site) ?;
594
+ for req in reqs {
595
+ write ! ( f, " {:?}" , req) ?;
596
+ }
597
+ writeln ! ( f, "]" )
545
598
}
546
599
}
547
600
@@ -552,11 +605,11 @@ impl Queue {
552
605
store : Arc < SyncStore > ,
553
606
capacity : usize ,
554
607
registry : Arc < MetricsRegistry > ,
555
- ) -> Arc < Self > {
608
+ ) -> ( Arc < Self > , JoinHandle < ( ) > ) {
556
609
async fn start_writer ( queue : Arc < Queue > , logger : Logger ) {
557
610
loop {
558
611
#[ cfg( debug_assertions) ]
559
- test_support:: take_step ( ) . await ;
612
+ test_support:: take_step ( & queue . store . site . as_ref ( ) . into ( ) ) . await ;
560
613
561
614
// We peek at the front of the queue, rather than pop it
562
615
// right away, so that query methods like `get` have access
@@ -623,9 +676,9 @@ impl Queue {
623
676
} ;
624
677
let queue = Arc :: new ( queue) ;
625
678
626
- graph:: spawn ( start_writer ( queue. cheap_clone ( ) , logger) ) ;
679
+ let handle = graph:: spawn ( start_writer ( queue. cheap_clone ( ) , logger) ) ;
627
680
628
- queue
681
+ ( queue, handle )
629
682
}
630
683
631
684
/// Add a write request to the queue
@@ -637,6 +690,7 @@ impl Queue {
637
690
638
691
/// Wait for the background writer to finish processing queued entries
639
692
async fn flush ( & self ) -> Result < ( ) , StoreError > {
693
+ self . check_err ( ) ?;
640
694
self . queue . wait_empty ( ) . await ;
641
695
self . check_err ( )
642
696
}
@@ -880,7 +934,10 @@ impl Queue {
880
934
/// A shim to allow bypassing any pipelined store handling if need be
881
935
enum Writer {
882
936
Sync ( Arc < SyncStore > ) ,
883
- Async ( Arc < Queue > ) ,
937
+ Async {
938
+ queue : Arc < Queue > ,
939
+ join_handle : JoinHandle < ( ) > ,
940
+ } ,
884
941
}
885
942
886
943
impl Writer {
@@ -894,7 +951,24 @@ impl Writer {
894
951
if capacity == 0 {
895
952
Self :: Sync ( store)
896
953
} else {
897
- Self :: Async ( Queue :: start ( logger, store, capacity, registry) )
954
+ let ( queue, join_handle) = Queue :: start ( logger, store. clone ( ) , capacity, registry) ;
955
+ Self :: Async { queue, join_handle }
956
+ }
957
+ }
958
+
959
+ fn check_queue_running ( & self ) -> Result < ( ) , StoreError > {
960
+ match self {
961
+ Writer :: Sync ( _) => Ok ( ( ) ) ,
962
+ Writer :: Async { join_handle, queue } => {
963
+ if join_handle. is_finished ( ) {
964
+ Err ( constraint_violation ! (
965
+ "Subgraph writer for {} is not running" ,
966
+ queue. store. site
967
+ ) )
968
+ } else {
969
+ Ok ( ( ) )
970
+ }
971
+ }
898
972
}
899
973
}
900
974
@@ -920,7 +994,8 @@ impl Writer {
920
994
& manifest_idx_and_name,
921
995
& processed_data_sources,
922
996
) ,
923
- Writer :: Async ( queue) => {
997
+ Writer :: Async { queue, .. } => {
998
+ self . check_queue_running ( ) ?;
924
999
let req = Request :: Write {
925
1000
store : queue. store . cheap_clone ( ) ,
926
1001
stopwatch : queue. stopwatch . cheap_clone ( ) ,
@@ -944,7 +1019,8 @@ impl Writer {
944
1019
) -> Result < ( ) , StoreError > {
945
1020
match self {
946
1021
Writer :: Sync ( store) => store. revert_block_operations ( block_ptr_to, & firehose_cursor) ,
947
- Writer :: Async ( queue) => {
1022
+ Writer :: Async { queue, .. } => {
1023
+ self . check_queue_running ( ) ?;
948
1024
let req = Request :: RevertTo {
949
1025
store : queue. store . cheap_clone ( ) ,
950
1026
block_ptr : block_ptr_to,
@@ -958,14 +1034,17 @@ impl Writer {
958
1034
async fn flush ( & self ) -> Result < ( ) , StoreError > {
959
1035
match self {
960
1036
Writer :: Sync { .. } => Ok ( ( ) ) ,
961
- Writer :: Async ( queue) => queue. flush ( ) . await ,
1037
+ Writer :: Async { queue, .. } => {
1038
+ self . check_queue_running ( ) ?;
1039
+ queue. flush ( ) . await
1040
+ }
962
1041
}
963
1042
}
964
1043
965
1044
fn get ( & self , key : & EntityKey ) -> Result < Option < Entity > , StoreError > {
966
1045
match self {
967
1046
Writer :: Sync ( store) => store. get ( key, BLOCK_NUMBER_MAX ) ,
968
- Writer :: Async ( queue) => queue. get ( key) ,
1047
+ Writer :: Async { queue, .. } => queue. get ( key) ,
969
1048
}
970
1049
}
971
1050
@@ -975,7 +1054,7 @@ impl Writer {
975
1054
) -> Result < BTreeMap < EntityKey , Entity > , StoreError > {
976
1055
match self {
977
1056
Writer :: Sync ( store) => store. get_many ( keys, BLOCK_NUMBER_MAX ) ,
978
- Writer :: Async ( queue) => queue. get_many ( keys) ,
1057
+ Writer :: Async { queue, .. } => queue. get_many ( keys) ,
979
1058
}
980
1059
}
981
1060
@@ -985,7 +1064,7 @@ impl Writer {
985
1064
) -> Result < BTreeMap < EntityKey , Entity > , StoreError > {
986
1065
match self {
987
1066
Writer :: Sync ( store) => store. get_derived ( key, BLOCK_NUMBER_MAX , vec ! [ ] ) ,
988
- Writer :: Async ( queue) => queue. get_derived ( key) ,
1067
+ Writer :: Async { queue, .. } => queue. get_derived ( key) ,
989
1068
}
990
1069
}
991
1070
@@ -999,28 +1078,30 @@ impl Writer {
999
1078
. load_dynamic_data_sources ( BLOCK_NUMBER_MAX , manifest_idx_and_name)
1000
1079
. await
1001
1080
}
1002
- Writer :: Async ( queue) => queue. load_dynamic_data_sources ( manifest_idx_and_name) . await ,
1081
+ Writer :: Async { queue, .. } => {
1082
+ queue. load_dynamic_data_sources ( manifest_idx_and_name) . await
1083
+ }
1003
1084
}
1004
1085
}
1005
1086
1006
1087
fn poisoned ( & self ) -> bool {
1007
1088
match self {
1008
1089
Writer :: Sync ( _) => false ,
1009
- Writer :: Async ( queue) => queue. poisoned ( ) ,
1090
+ Writer :: Async { queue, .. } => queue. poisoned ( ) ,
1010
1091
}
1011
1092
}
1012
1093
1013
1094
async fn stop ( & self ) -> Result < ( ) , StoreError > {
1014
1095
match self {
1015
1096
Writer :: Sync ( _) => Ok ( ( ) ) ,
1016
- Writer :: Async ( queue) => queue. stop ( ) . await ,
1097
+ Writer :: Async { queue, .. } => queue. stop ( ) . await ,
1017
1098
}
1018
1099
}
1019
1100
1020
1101
fn deployment_synced ( & self ) {
1021
1102
match self {
1022
1103
Writer :: Sync ( _) => { }
1023
- Writer :: Async ( queue) => queue. deployment_synced ( ) ,
1104
+ Writer :: Async { queue, .. } => queue. deployment_synced ( ) ,
1024
1105
}
1025
1106
}
1026
1107
}
0 commit comments