1+ use lazy_static:: lazy_static;
2+
13use std:: { collections:: HashMap , sync:: Arc , time:: Duration } ;
24
3- use futures03:: TryFutureExt ;
4- use slog:: { o, Logger } ;
55use tokio:: sync:: { mpsc, watch:: Receiver , RwLock } ;
66
7- use crate :: prelude:: LoggerFactory ;
8-
97use super :: store:: DeploymentId ;
108
119const DEFAULT_BUFFER_SIZE : usize = 100 ;
10+ #[ cfg( not( test) ) ]
11+ const INDEXER_WATCHER_INTERVAL : Duration = Duration :: from_secs ( 10 ) ;
12+ #[ cfg( test) ]
13+ const INDEXER_WATCHER_INTERVAL : Duration = Duration :: from_millis ( 100 ) ;
14+ lazy_static ! {
15+ pub static ref TRACING_RUNTIME : tokio:: runtime:: Runtime =
16+ tokio:: runtime:: Builder :: new_multi_thread( )
17+ . worker_threads( 1 )
18+ . enable_all( )
19+ . build( )
20+ . unwrap( ) ;
21+ }
1222
1323#[ derive( Debug , Clone ) ]
1424pub struct Subscriptions < T > {
@@ -33,59 +43,42 @@ pub struct TracingControl<T> {
3343 default_buffer_size : usize ,
3444}
3545
36- // impl<T: Send + Clone + 'static> Default for TracingControl<T> {
37- // fn default() -> Self {
38- // let subscriptions = Subscriptions::default();
39- // let subs = subscriptions.clone();
40- // let watcher = std::thread::spawn(move || {
41- // let runtime = tokio::runtime::Builder::new_multi_thread()
42- // .enable_all()
43- // .build()
44- // .unwrap();
45- // runtime.block_on()
46- // })
47- // .join()
48- // .unwrap()
49- // .unwrap();
50-
51- // Self {
52- // subscriptions,
53- // default_buffer_size: DEFAULT_BUFFER_SIZE,
54- // watcher,
55- // }
56- // }
57- // }
58-
5946impl < T : Send + Clone + ' static > TracingControl < T > {
60- pub async fn start ( ) -> Self {
47+ /// Starts a new tracing control instance.If an async runtime is not available, a new one will be created.
48+ pub fn start ( ) -> Self {
49+ Self :: new ( DEFAULT_BUFFER_SIZE )
50+ }
51+
52+ pub fn new ( buffer_size : usize ) -> Self {
6153 let subscriptions = Subscriptions :: default ( ) ;
6254 let subs = subscriptions. clone ( ) ;
63- let watcher = indexer_watcher:: new_watcher (
64- #[ cfg( test) ]
65- Duration :: from_millis ( 100 ) ,
66- #[ cfg( not( test) ) ]
67- Duration :: from_secs ( 30 ) ,
68- move || {
69- let subs = subs. clone ( ) ;
70-
71- async move { Ok ( subs. inner . read ( ) . await . clone ( ) ) }
72- } ,
73- )
74- . await
55+
56+ let watcher = std:: thread:: spawn ( move || {
57+ let handle =
58+ tokio:: runtime:: Handle :: try_current ( ) . unwrap_or ( TRACING_RUNTIME . handle ( ) . clone ( ) ) ;
59+
60+ handle. block_on ( async move {
61+ indexer_watcher:: new_watcher ( INDEXER_WATCHER_INTERVAL , move || {
62+ let subs = subs. clone ( ) ;
63+
64+ async move { Ok ( subs. inner . read ( ) . await . clone ( ) ) }
65+ } )
66+ . await
67+ } )
68+ } )
69+ . join ( )
70+ . unwrap ( )
7571 . unwrap ( ) ;
72+
7673 Self {
7774 watcher,
7875 subscriptions,
79- default_buffer_size : DEFAULT_BUFFER_SIZE ,
76+ default_buffer_size : buffer_size ,
8077 }
8178 }
82- // pub fn new(default_buffer_size: Option<usize>) -> Self {
83- // Self {
84- // default_buffer_size: default_buffer_size.unwrap_or(DEFAULT_BUFFER_SIZE),
85- // ..Default::default()
86- // }
87- // }
8879
80+ /// Returns a producer for a given deployment ID. If the producer is closed, it will return None.
81+ /// The producer could still be closed in the meantime.
8982 pub fn producer ( & self , key : DeploymentId ) -> Option < mpsc:: Sender < T > > {
9083 self . watcher
9184 . borrow ( )
@@ -94,6 +87,8 @@ impl<T: Send + Clone + 'static> TracingControl<T> {
9487 . filter ( |sender| !sender. is_closed ( ) )
9588 }
9689
90+ /// Creates a new subscription for a given deployment ID with a given buffer size. If a subscription already
91+ /// exists, it will be replaced.
9792 pub async fn subscribe_with_chan_size (
9893 & self ,
9994 key : DeploymentId ,
@@ -118,26 +113,53 @@ impl<T: Send + Clone + 'static> TracingControl<T> {
118113mod test {
119114
120115 use anyhow:: anyhow;
116+ use tokio:: time:: { self , Instant } ;
121117 use tokio_retry:: Retry ;
122118
123119 use super :: * ;
124- use std:: { future:: IntoFuture , sync:: Arc } ;
120+ use std:: sync:: Arc ;
121+
122+ #[ tokio:: test]
123+ async fn test_watcher ( ) {
124+ let x = time:: Instant :: now ( ) ;
125+ let x = indexer_watcher:: new_watcher ( Duration :: from_millis ( 10 ) , move || {
126+ let x = x. clone ( ) ;
127+
128+ async move {
129+ let now = Instant :: now ( ) ;
130+ Ok ( now. duration_since ( x) )
131+ }
132+ } )
133+ . await
134+ . unwrap ( ) ;
135+
136+ Retry :: spawn ( vec ! [ Duration :: from_secs( 10 ) ; 3 ] . into_iter ( ) , move || {
137+ let x = x. clone ( ) ;
138+ async move {
139+ let count = x. borrow ( ) . clone ( ) ;
140+ println ! ( "{}" , count. as_millis( ) ) ;
141+ Err :: < Duration , anyhow:: Error > ( anyhow ! ( "millis: {}" , count. as_millis( ) ) )
142+ }
143+ } )
144+ . await
145+ . unwrap ( ) ;
146+ }
125147
126148 #[ tokio:: test]
127149 async fn test_tracing_control ( ) {
128- let control: TracingControl < ( ) > = TracingControl :: start ( ) . await ;
150+ let control: TracingControl < ( ) > = TracingControl :: start ( ) ;
129151 let control = Arc :: new ( control) ;
130152
131153 // produce before subscription
132154 let tx = control. producer ( DeploymentId ( 123 ) ) ;
133155 assert ! ( tx. is_none( ) ) ;
134156
135157 // drop the subscription
136- let rx = control. subscribe ( DeploymentId ( 123 ) ) ;
158+ let rx = control. subscribe ( DeploymentId ( 123 ) ) . await ;
137159
138160 let c = control. clone ( ) ;
139161 // check subscription is none because channel is closed
140- let tx = Retry :: spawn ( vec ! [ Duration :: from_secs ( 5 ) ; 10 ] . into_iter ( ) , move || {
162+ let tx = Retry :: spawn ( vec ! [ INDEXER_WATCHER_INTERVAL ; 2 ] . into_iter ( ) , move || {
141163 let control = c. clone ( ) ;
142164 async move {
143165 match control. producer ( DeploymentId ( 123 ) ) {
@@ -158,9 +180,22 @@ mod test {
158180 assert ! ( tx. is_none( ) ) ;
159181
160182 // re-create subscription
161- let _rx = control. subscribe ( DeploymentId ( 123 ) ) ;
183+ let _rx = control. subscribe ( DeploymentId ( 123 ) ) . await ;
184+
162185 // check old subscription was replaced
163- let tx = control. producer ( DeploymentId ( 123 ) ) ;
164- assert ! ( !tx. unwrap( ) . is_closed( ) )
186+ let c = control. clone ( ) ;
187+ let tx = Retry :: spawn ( vec ! [ INDEXER_WATCHER_INTERVAL ; 2 ] . into_iter ( ) , move || {
188+ let tx = c. producer ( DeploymentId ( 123 ) ) ;
189+ async move {
190+ match tx {
191+ Some ( sender) if !sender. is_closed ( ) => Ok ( sender) ,
192+ Some ( _) => Err ( anyhow ! ( "Sender is closed" ) ) ,
193+ None => Err ( anyhow ! ( "Sender not created yet" ) ) ,
194+ }
195+ }
196+ } )
197+ . await
198+ . unwrap ( ) ;
199+ assert ! ( !tx. is_closed( ) )
165200 }
166201}
0 commit comments