11use std:: time:: { Duration , Instant } ;
22
33use anyhow:: { anyhow, Result } ;
4- use tracing:: warn ;
4+ use tracing:: error ;
55
66#[ derive( Debug , Clone , Copy ) ]
77pub struct BlockingCallPolicy {
@@ -23,7 +23,7 @@ impl BlockingCallPolicy {
2323 . ok ( )
2424 . and_then ( |v| v. parse :: < u64 > ( ) . ok ( ) )
2525 . map ( Duration :: from_millis)
26- . unwrap_or_else ( || Duration :: from_secs ( 5 ) ) ;
26+ . unwrap_or_else ( || Duration :: from_secs ( 30 ) ) ;
2727 let max_retries = std:: env:: var ( max_retries_var)
2828 . ok ( )
2929 . and_then ( |v| v. parse :: < usize > ( ) . ok ( ) )
@@ -83,78 +83,52 @@ where
8383 OnRetry : FnMut ( ) ,
8484 OnTimeout : FnMut ( ) ,
8585{
86- let mut attempts = 0usize ;
87- loop {
88- let start = Instant :: now ( ) ;
89- let ( tx, rx) = std:: sync:: mpsc:: sync_channel ( 1 ) ;
90- let op_fn = build ( ) ;
86+ let _ = (
87+ & policy. max_retries ,
88+ & policy. retry_backoff ,
89+ & policy. retry_on_timeout ,
90+ ) ;
91+ let _ = & mut on_retry;
9192
92- if let Ok ( handle) = tokio:: runtime:: Handle :: try_current ( ) {
93- handle. spawn_blocking ( move || {
94- let _ = tx. send ( op_fn ( ) ) ;
95- } ) ;
96- } else {
97- std:: thread:: spawn ( move || {
98- let _ = tx. send ( op_fn ( ) ) ;
99- } ) ;
100- }
93+ let start = Instant :: now ( ) ;
94+ let ( tx, rx) = std:: sync:: mpsc:: sync_channel ( 1 ) ;
95+ let op_fn = build ( ) ;
10196
102- match rx. recv_timeout ( policy. timeout ) {
103- Ok ( result) => {
104- on_op ( start. elapsed ( ) . as_micros ( ) as u64 ) ;
105- if result. is_err ( ) && attempts < policy. max_retries {
106- attempts += 1 ;
107- on_retry ( ) ;
108- warn ! (
109- op = op,
110- keyspace = keyspace,
111- attempt = attempts,
112- max_retries = policy. max_retries,
113- "retrying failed blocking call"
114- ) ;
115- continue ;
116- }
117- return result;
118- }
119- Err ( std:: sync:: mpsc:: RecvTimeoutError :: Timeout ) => {
120- on_op ( start. elapsed ( ) . as_micros ( ) as u64 ) ;
121- on_timeout ( ) ;
122- if policy. retry_on_timeout && attempts < policy. max_retries {
123- attempts += 1 ;
124- on_retry ( ) ;
125- warn ! (
126- op = op,
127- keyspace = keyspace,
128- attempt = attempts,
129- max_retries = policy. max_retries,
130- timeout_ms = policy. timeout. as_millis( ) ,
131- "blocking call timed out; retrying"
132- ) ;
133- continue ;
134- }
135- return Err ( anyhow ! (
136- "blocking call {} on {} exceeded timeout budget ({} ms)" ,
137- op,
138- keyspace,
139- policy. timeout. as_millis( )
140- ) ) ;
141- }
142- Err ( std:: sync:: mpsc:: RecvTimeoutError :: Disconnected ) => {
143- on_op ( start. elapsed ( ) . as_micros ( ) as u64 ) ;
144- if attempts < policy. max_retries {
145- attempts += 1 ;
146- on_retry ( ) ;
147- warn ! (
148- op = op,
149- keyspace = keyspace,
150- attempt = attempts,
151- max_retries = policy. max_retries,
152- "retrying blocking call after worker disconnect"
153- ) ;
154- continue ;
155- }
156- return Err ( anyhow ! ( "blocking worker disconnected while running {}" , op) ) ;
97+ if let Ok ( handle) = tokio:: runtime:: Handle :: try_current ( ) {
98+ handle. spawn_blocking ( move || {
99+ let _ = tx. send ( op_fn ( ) ) ;
100+ } ) ;
101+ } else {
102+ std:: thread:: spawn ( move || {
103+ let _ = tx. send ( op_fn ( ) ) ;
104+ } ) ;
105+ }
106+
107+ match rx. recv_timeout ( policy. timeout ) {
108+ Ok ( result) => {
109+ on_op ( start. elapsed ( ) . as_micros ( ) as u64 ) ;
110+ if let Err ( ref err) = result {
111+ error ! ( op = op, keyspace = keyspace, error = %err, "blocking call failed" ) ;
157112 }
113+ result
114+ }
115+ Err ( std:: sync:: mpsc:: RecvTimeoutError :: Timeout ) => {
116+ on_op ( start. elapsed ( ) . as_micros ( ) as u64 ) ;
117+ on_timeout ( ) ;
118+ let err = anyhow ! (
119+ "blocking call {} on {} exceeded timeout budget ({} ms)" ,
120+ op,
121+ keyspace,
122+ policy. timeout. as_millis( )
123+ ) ;
124+ error ! ( op = op, keyspace = keyspace, error = %err, "blocking call timed out" ) ;
125+ Err ( err)
126+ }
127+ Err ( std:: sync:: mpsc:: RecvTimeoutError :: Disconnected ) => {
128+ on_op ( start. elapsed ( ) . as_micros ( ) as u64 ) ;
129+ let err = anyhow ! ( "blocking worker disconnected while running {}" , op) ;
130+ error ! ( op = op, keyspace = keyspace, error = %err, "blocking worker disconnected" ) ;
131+ Err ( err)
158132 }
159133 }
160134}
@@ -176,75 +150,45 @@ where
176150 OnRetry : FnMut ( ) ,
177151 OnTimeout : FnMut ( ) ,
178152{
179- let mut attempts = 0usize ;
180- loop {
181- let start = Instant :: now ( ) ;
182- let handle = tokio:: task:: spawn_blocking ( build ( ) ) ;
183- let timed = tokio:: time:: timeout ( policy. timeout , handle) . await ;
184- match timed {
185- Ok ( joined) => match joined {
186- Ok ( Ok ( value) ) => {
187- on_op ( start. elapsed ( ) . as_micros ( ) as u64 ) ;
188- return Ok ( value) ;
189- }
190- Ok ( Err ( err) ) => {
191- on_op ( start. elapsed ( ) . as_micros ( ) as u64 ) ;
192- if attempts >= policy. max_retries {
193- return Err ( err) ;
194- }
195- attempts += 1 ;
196- on_retry ( ) ;
197- warn ! (
198- op = op,
199- keyspace = keyspace,
200- attempt = attempts,
201- max_retries = policy. max_retries,
202- "retrying failed blocking call"
203- ) ;
204- }
205- Err ( join_err) => {
206- on_op ( start. elapsed ( ) . as_micros ( ) as u64 ) ;
207- if attempts >= policy. max_retries {
208- return Err ( anyhow ! ( "blocking task join error: {}" , join_err) ) ;
209- }
210- attempts += 1 ;
211- on_retry ( ) ;
212- warn ! (
213- op = op,
214- keyspace = keyspace,
215- attempt = attempts,
216- max_retries = policy. max_retries,
217- error = %join_err,
218- "retrying blocking call after join error"
219- ) ;
220- }
221- } ,
222- Err ( _) => {
153+ let _ = (
154+ & policy. max_retries ,
155+ & policy. retry_backoff ,
156+ & policy. retry_on_timeout ,
157+ ) ;
158+ let _ = & mut on_retry;
159+
160+ let start = Instant :: now ( ) ;
161+ let handle = tokio:: task:: spawn_blocking ( build ( ) ) ;
162+ let timed = tokio:: time:: timeout ( policy. timeout , handle) . await ;
163+ match timed {
164+ Ok ( joined) => match joined {
165+ Ok ( Ok ( value) ) => {
223166 on_op ( start. elapsed ( ) . as_micros ( ) as u64 ) ;
224- on_timeout ( ) ;
225- if policy. retry_on_timeout && attempts < policy. max_retries {
226- attempts += 1 ;
227- on_retry ( ) ;
228- warn ! (
229- op = op,
230- keyspace = keyspace,
231- attempt = attempts,
232- max_retries = policy. max_retries,
233- timeout_ms = policy. timeout. as_millis( ) ,
234- "blocking call timed out; retrying"
235- ) ;
236- } else {
237- return Err ( anyhow ! (
238- "blocking call timed out after {} ms (op={}, keyspace={})" ,
239- policy. timeout. as_millis( ) ,
240- op,
241- keyspace
242- ) ) ;
243- }
167+ Ok ( value)
244168 }
245- }
246- if !policy. retry_backoff . is_zero ( ) {
247- tokio:: time:: sleep ( policy. retry_backoff ) . await ;
169+ Ok ( Err ( err) ) => {
170+ on_op ( start. elapsed ( ) . as_micros ( ) as u64 ) ;
171+ error ! ( op = op, keyspace = keyspace, error = %err, "blocking call failed" ) ;
172+ Err ( err)
173+ }
174+ Err ( join_err) => {
175+ on_op ( start. elapsed ( ) . as_micros ( ) as u64 ) ;
176+ let err = anyhow ! ( "blocking task join error: {}" , join_err) ;
177+ error ! ( op = op, keyspace = keyspace, error = %err, "blocking task join error" ) ;
178+ Err ( err)
179+ }
180+ } ,
181+ Err ( _) => {
182+ on_op ( start. elapsed ( ) . as_micros ( ) as u64 ) ;
183+ on_timeout ( ) ;
184+ let err = anyhow ! (
185+ "blocking call timed out after {} ms (op={}, keyspace={})" ,
186+ policy. timeout. as_millis( ) ,
187+ op,
188+ keyspace
189+ ) ;
190+ error ! ( op = op, keyspace = keyspace, error = %err, "blocking call timed out" ) ;
191+ Err ( err)
248192 }
249193 }
250194}
0 commit comments