88
99use futures_util:: { future:: BoxFuture , stream:: Stream } ;
1010use std:: { fmt:: Debug , future:: Future , time:: Duration } ;
11+ use futures_util:: stream:: unfold;
1112use thiserror:: Error ;
1213
1314/// A runtime is an abstraction of an async runtime like [Tokio] or [async-std]. It allows
14- /// OpenTelemetry to work with any current and hopefully future runtime implementation .
15+ /// OpenTelemetry to work with any current and hopefully future runtime implementations .
1516///
1617/// [Tokio]: https://crates.io/crates/tokio
1718/// [async-std]: https://crates.io/crates/async-std
19+ ///
20+ /// # Note
21+ ///
22+ /// OpenTelemetry expects a *multi-threaded* runtime because its types can move across threads.
23+ /// For this reason, this trait requires the `Send` and `Sync` bounds. Single-threaded runtimes
24+ /// can implement this trait in a way that spawns the tasks on the same thread as the calling code.
1825#[ cfg( feature = "experimental_async_runtime" ) ]
1926pub trait Runtime : Clone + Send + Sync + ' static {
20- /// A future stream, which returns items in a previously specified interval. The item type is
21- /// not important.
22- type Interval : Stream + Send ;
23-
24- /// A future, which resolves after a previously specified amount of time. The output type is
25- /// not important.
26- type Delay : Future + Send + Unpin ;
27-
28- /// Create a [futures_util::stream::Stream], which returns a new item every
29- /// [std::time::Duration].
30- fn interval ( & self , duration : Duration ) -> Self :: Interval ;
31-
3227 /// Spawn a new task or thread, which executes the given future.
3328 ///
3429 /// # Note
3530 ///
3631 /// This is mainly used to run batch span processing in the background. Note, that the function
3732 /// does not return a handle. OpenTelemetry will use a different way to wait for the future to
38- /// finish when TracerProvider gets shutdown. At the moment this happens by blocking the
33+ /// finish when ` TracerProvider` gets shutdown. At the moment this happens by blocking the
3934 /// current thread. This means runtime implementations need to make sure they can still execute
4035 /// the given future even if the main thread is blocked.
4136 fn spawn ( & self , future : BoxFuture < ' static , ( ) > ) ;
4237
4338 /// Return a new future, which resolves after the specified [std::time::Duration].
44- fn delay ( & self , duration : Duration ) -> Self :: Delay ;
39+ fn delay ( & self , duration : Duration ) -> impl Future < Output = ( ) > + Send + Sync + ' static ;
40+ }
41+
42+ /// Uses the given runtime to produce an interval stream.
43+ #[ cfg( feature = "experimental_async_runtime" ) ]
44+ pub ( crate ) fn to_interval_stream < T : Runtime > ( runtime : T , interval : Duration ) -> impl Stream < Item = ( ) > {
45+ unfold ( ( ) , move |_| {
46+ let runtime_cloned = runtime. clone ( ) ;
47+
48+ async move {
49+ runtime_cloned. delay ( interval) . await ;
50+ Some ( ( ( ) , ( ) ) )
51+ }
52+ } )
4553}
4654
4755/// Runtime implementation, which works with Tokio's multi thread runtime.
@@ -59,21 +67,14 @@ pub struct Tokio;
5967 doc( cfg( all( feature = "experimental_async_runtime" , feature = "rt-tokio" ) ) )
6068) ]
6169impl Runtime for Tokio {
62- type Interval = tokio_stream:: wrappers:: IntervalStream ;
63- type Delay = :: std:: pin:: Pin < Box < tokio:: time:: Sleep > > ;
64-
65- fn interval ( & self , duration : Duration ) -> Self :: Interval {
66- crate :: util:: tokio_interval_stream ( duration)
67- }
68-
6970 fn spawn ( & self , future : BoxFuture < ' static , ( ) > ) {
7071 #[ allow( clippy:: let_underscore_future) ]
7172 // we don't have to await on the returned future to execute
7273 let _ = tokio:: spawn ( future) ;
7374 }
7475
75- fn delay ( & self , duration : Duration ) -> Self :: Delay {
76- Box :: pin ( tokio:: time:: sleep ( duration) )
76+ fn delay ( & self , duration : Duration ) -> impl Future < Output = ( ) > + Send + Sync + ' static {
77+ tokio:: time:: sleep ( duration)
7778 }
7879}
7980
@@ -104,13 +105,6 @@ pub struct TokioCurrentThread;
104105 ) ) )
105106) ]
106107impl Runtime for TokioCurrentThread {
107- type Interval = tokio_stream:: wrappers:: IntervalStream ;
108- type Delay = :: std:: pin:: Pin < Box < tokio:: time:: Sleep > > ;
109-
110- fn interval ( & self , duration : Duration ) -> Self :: Interval {
111- crate :: util:: tokio_interval_stream ( duration)
112- }
113-
114108 fn spawn ( & self , future : BoxFuture < ' static , ( ) > ) {
115109 // We cannot force push tracing in current thread tokio scheduler because we rely on
116110 // BatchSpanProcessor to export spans in a background task, meanwhile we need to block the
@@ -127,8 +121,8 @@ impl Runtime for TokioCurrentThread {
127121 } ) ;
128122 }
129123
130- fn delay ( & self , duration : Duration ) -> Self :: Delay {
131- Box :: pin ( tokio:: time:: sleep ( duration) )
124+ fn delay ( & self , duration : Duration ) -> impl Future < Output = ( ) > + Send + Sync + ' static {
125+ tokio:: time:: sleep ( duration)
132126 }
133127}
134128
@@ -147,20 +141,13 @@ pub struct AsyncStd;
147141 doc( cfg( all( feature = "experimental_async_runtime" , feature = "rt-async-std" ) ) )
148142) ]
149143impl Runtime for AsyncStd {
150- type Interval = async_std:: stream:: Interval ;
151- type Delay = BoxFuture < ' static , ( ) > ;
152-
153- fn interval ( & self , duration : Duration ) -> Self :: Interval {
154- async_std:: stream:: interval ( duration)
155- }
156-
157144 fn spawn ( & self , future : BoxFuture < ' static , ( ) > ) {
158145 #[ allow( clippy:: let_underscore_future) ]
159146 let _ = async_std:: task:: spawn ( future) ;
160147 }
161148
162- fn delay ( & self , duration : Duration ) -> Self :: Delay {
163- Box :: pin ( async_std:: task:: sleep ( duration) )
149+ fn delay ( & self , duration : Duration ) -> impl Future < Output = ( ) > + Send + Sync + ' static {
150+ async_std:: task:: sleep ( duration)
164151 }
165152}
166153
@@ -193,7 +180,7 @@ pub enum TrySendError {
193180 /// Send failed due to the channel being closed.
194181 #[ error( "cannot send message to batch processor as the channel is closed" ) ]
195182 ChannelClosed ,
196- /// Any other send error that isnt covered above.
183+ /// Any other send error that isn't covered above.
197184 #[ error( transparent) ]
198185 Other ( #[ from] Box < dyn std:: error:: Error + Send + Sync + ' static > ) ,
199186}
0 commit comments