@@ -2,14 +2,15 @@ use graph::{
22 blockchain:: ChainHeadUpdateStream ,
33 prelude:: {
44 futures03:: { self , FutureExt } ,
5- tokio, StoreError ,
5+ tokio:: { self , task:: JoinHandle } ,
6+ StoreError ,
67 } ,
78 prometheus:: { CounterVec , GaugeVec } ,
89 util:: timed_rw_lock:: TimedRwLock ,
910} ;
10- use std:: sync:: { atomic:: AtomicBool , Arc } ;
11+ use std:: str:: FromStr ;
12+ use std:: sync:: Arc ;
1113use std:: { collections:: BTreeMap , time:: Duration } ;
12- use std:: { str:: FromStr , sync:: atomic} ;
1314
1415use lazy_static:: lazy_static;
1516
@@ -151,7 +152,7 @@ impl ChainHeadUpdateListener {
151152 ) {
152153 // Process chain head updates in a dedicated task
153154 graph:: spawn ( async move {
154- let sending_to_watcher = Arc :: new ( AtomicBool :: new ( false ) ) ;
155+ let mut send_to_watcher : Option < JoinHandle < ( ) > > = None ;
155156 while let Some ( notification) = receiver. recv ( ) . await {
156157 // Create ChainHeadUpdate from JSON
157158 let update: ChainHeadUpdate =
@@ -180,16 +181,16 @@ impl ChainHeadUpdateListener {
180181 if let Some ( watcher) = watchers. read ( & logger) . get ( & update. network_name ) {
181182 // Due to a tokio bug, we must assume that the watcher can deadlock, see
182183 // https://github.com/tokio-rs/tokio/issues/4246.
183- if !sending_to_watcher . load ( atomic :: Ordering :: SeqCst ) {
184- let sending_to_watcher = sending_to_watcher . cheap_clone ( ) ;
185- let sender = watcher. sender . cheap_clone ( ) ;
186- tokio:: task:: spawn_blocking ( move || {
187- sending_to_watcher . store ( true , atomic :: Ordering :: SeqCst ) ;
188- sender . send ( ( ) ) . unwrap ( ) ;
189- sending_to_watcher . store ( false , atomic :: Ordering :: SeqCst ) ;
190- } ) ;
191- } else {
192- debug ! ( logger , "skipping chain head update, watcher is deadlocked" ; "network" => & update . network_name ) ;
184+ match send_to_watcher . as_mut ( ) . map ( FutureExt :: now_or_never ) {
185+ None | Some ( Some ( _ ) ) => {
186+ let sender = watcher. sender . cheap_clone ( ) ;
187+ send_to_watcher = Some ( tokio:: task:: spawn_blocking ( move || {
188+ sender . send ( ( ) ) . unwrap ( )
189+ } ) ) ;
190+ }
191+ Some ( None ) => {
192+ debug ! ( logger , "skipping chain head update, watcher is deadlocked" ; "network" => & update . network_name )
193+ }
193194 }
194195 }
195196 }
0 commit comments