1+ use super :: metrics;
12use super :: { BroadcastedView , WriteCommand } ;
23use super :: { Delta , Durability , WriteError , WriteResult } ;
34use crate :: StorageRead ;
@@ -6,7 +7,7 @@ use crate::storage::StorageSnapshot;
67use futures:: FutureExt ;
78use futures:: future:: Shared ;
89use std:: sync:: Arc ;
9- use std:: time:: Duration ;
10+ use std:: time:: { Duration , Instant } ;
1011use tokio:: sync:: { broadcast, mpsc, oneshot, watch} ;
1112
1213/// A point-in-time view of all applied writes, broadcast by the coordinator
@@ -142,18 +143,21 @@ impl<M: Clone + Send + 'static> WriteHandle<M> {
142143/// This is the main interface for interacting with the write coordinator.
143144/// It can be cloned and shared across tasks.
144145pub struct WriteCoordinatorHandle < D : Delta > {
146+ name : Arc < str > ,
145147 write_tx : mpsc:: Sender < WriteCommand < D > > ,
146148 watchers : EpochWatcher ,
147149 view : Arc < BroadcastedView < D > > ,
148150}
149151
150152impl < D : Delta > WriteCoordinatorHandle < D > {
151153 pub ( crate ) fn new (
154+ name : String ,
152155 write_tx : mpsc:: Sender < WriteCommand < D > > ,
153156 watchers : EpochWatcher ,
154157 view : Arc < BroadcastedView < D > > ,
155158 ) -> Self {
156159 Self {
160+ name : Arc :: from ( name) ,
157161 write_tx,
158162 watchers,
159163 view,
@@ -167,6 +171,35 @@ impl<D: Delta> WriteCoordinatorHandle<D> {
167171 pub fn flushed_epoch ( & self ) -> u64 {
168172 * self . watchers . written_rx . borrow ( )
169173 }
174+
175+ /// Sample queue depth on each send. Cheap atomic reads on `mpsc::Sender`.
176+ fn record_queue_depth ( & self ) {
177+ let max = self . write_tx . max_capacity ( ) ;
178+ let free = self . write_tx . capacity ( ) ;
179+ :: metrics:: gauge!(
180+ metrics:: COORDINATOR_QUEUE_DEPTH ,
181+ "channel" => self . name. to_string( ) ,
182+ )
183+ . set ( max. saturating_sub ( free) as f64 ) ;
184+ }
185+
186+ fn record_send ( & self , command : & ' static str , status : & ' static str , started : Instant ) {
187+ :: metrics:: histogram!(
188+ metrics:: COORDINATOR_SEND_DURATION_SECONDS ,
189+ "command" => command,
190+ "status" => status,
191+ )
192+ . record ( started. elapsed ( ) . as_secs_f64 ( ) ) ;
193+ }
194+
195+ fn record_backpressure ( & self , command : & ' static str , reason : & ' static str ) {
196+ :: metrics:: counter!(
197+ metrics:: COORDINATOR_QUEUE_BACKPRESSURE_TOTAL ,
198+ "command" => command,
199+ "reason" => reason,
200+ )
201+ . increment ( 1 ) ;
202+ }
170203}
171204
172205impl < D : Delta > WriteCoordinatorHandle < D > {
@@ -186,27 +219,37 @@ impl<D: Delta> WriteCoordinatorHandle<D> {
186219 write : D :: Write ,
187220 timeout : Duration ,
188221 ) -> Result < WriteHandle < D :: ApplyResult > , WriteError < D :: Write > > {
222+ const COMMAND : & str = "write_timeout" ;
223+ self . record_queue_depth ( ) ;
224+ let started = Instant :: now ( ) ;
189225 let ( tx, rx) = oneshot:: channel ( ) ;
190- self . write_tx
226+ let send_result = self
227+ . write_tx
191228 . send_timeout (
192229 WriteCommand :: Write {
193230 write,
194231 result_tx : tx,
195232 } ,
196233 timeout,
197234 )
198- . await
199- . map_err ( |e| match e {
200- mpsc:: error:: SendTimeoutError :: Timeout ( WriteCommand :: Write { write, .. } ) => {
201- WriteError :: TimeoutError ( write)
202- }
203- mpsc:: error:: SendTimeoutError :: Closed ( WriteCommand :: Write { write, .. } ) => {
204- WriteError :: Shutdown
205- }
206- _ => unreachable ! ( "sent a Write command" ) ,
207- } ) ?;
208-
209- Ok ( WriteHandle :: new ( rx, self . watchers . clone ( ) ) )
235+ . await ;
236+ match send_result {
237+ Ok ( ( ) ) => {
238+ self . record_send ( COMMAND , "ok" , started) ;
239+ Ok ( WriteHandle :: new ( rx, self . watchers . clone ( ) ) )
240+ }
241+ Err ( mpsc:: error:: SendTimeoutError :: Timeout ( WriteCommand :: Write { write, .. } ) ) => {
242+ self . record_send ( COMMAND , "timeout" , started) ;
243+ self . record_backpressure ( COMMAND , "timeout" ) ;
244+ Err ( WriteError :: TimeoutError ( write) )
245+ }
246+ Err ( mpsc:: error:: SendTimeoutError :: Closed ( WriteCommand :: Write { .. } ) ) => {
247+ self . record_send ( COMMAND , "shutdown" , started) ;
248+ self . record_backpressure ( COMMAND , "closed" ) ;
249+ Err ( WriteError :: Shutdown )
250+ }
251+ Err ( _) => unreachable ! ( "sent a Write command" ) ,
252+ }
210253 }
211254
212255 /// Submit a write to the coordinator, blocking indefinitely until there is
@@ -222,19 +265,29 @@ impl<D: Delta> WriteCoordinatorHandle<D> {
222265 & self ,
223266 write : D :: Write ,
224267 ) -> Result < WriteHandle < D :: ApplyResult > , WriteError < D :: Write > > {
268+ const COMMAND : & str = "write" ;
269+ self . record_queue_depth ( ) ;
270+ let started = Instant :: now ( ) ;
225271 let ( tx, rx) = oneshot:: channel ( ) ;
226- self . write_tx
272+ let send_result = self
273+ . write_tx
227274 . send ( WriteCommand :: Write {
228275 write,
229276 result_tx : tx,
230277 } )
231- . await
232- . map_err ( |e| match e {
233- mpsc:: error:: SendError ( WriteCommand :: Write { write, .. } ) => WriteError :: Shutdown ,
234- _ => unreachable ! ( "sent a Write command" ) ,
235- } ) ?;
236-
237- Ok ( WriteHandle :: new ( rx, self . watchers . clone ( ) ) )
278+ . await ;
279+ match send_result {
280+ Ok ( ( ) ) => {
281+ self . record_send ( COMMAND , "ok" , started) ;
282+ Ok ( WriteHandle :: new ( rx, self . watchers . clone ( ) ) )
283+ }
284+ Err ( mpsc:: error:: SendError ( WriteCommand :: Write { .. } ) ) => {
285+ self . record_send ( COMMAND , "shutdown" , started) ;
286+ self . record_backpressure ( COMMAND , "closed" ) ;
287+ Err ( WriteError :: Shutdown )
288+ }
289+ Err ( _) => unreachable ! ( "sent a Write command" ) ,
290+ }
238291 }
239292
240293 /// Submit a write to the coordinator.
@@ -247,23 +300,31 @@ impl<D: Delta> WriteCoordinatorHandle<D> {
247300 & self ,
248301 write : D :: Write ,
249302 ) -> Result < WriteHandle < D :: ApplyResult > , WriteError < D :: Write > > {
303+ const COMMAND : & str = "try_write" ;
304+ self . record_queue_depth ( ) ;
305+ let started = Instant :: now ( ) ;
250306 let ( tx, rx) = oneshot:: channel ( ) ;
251- self . write_tx
252- . try_send ( WriteCommand :: Write {
253- write,
254- result_tx : tx,
255- } )
256- . map_err ( |e| match e {
257- mpsc:: error:: TrySendError :: Full ( WriteCommand :: Write { write, .. } ) => {
258- WriteError :: Backpressure ( write)
259- }
260- mpsc:: error:: TrySendError :: Closed ( WriteCommand :: Write { write, .. } ) => {
261- WriteError :: Shutdown
262- }
263- _ => unreachable ! ( "sent a Write command" ) ,
264- } ) ?;
265-
266- Ok ( WriteHandle :: new ( rx, self . watchers . clone ( ) ) )
307+ let send_result = self . write_tx . try_send ( WriteCommand :: Write {
308+ write,
309+ result_tx : tx,
310+ } ) ;
311+ match send_result {
312+ Ok ( ( ) ) => {
313+ self . record_send ( COMMAND , "ok" , started) ;
314+ Ok ( WriteHandle :: new ( rx, self . watchers . clone ( ) ) )
315+ }
316+ Err ( mpsc:: error:: TrySendError :: Full ( WriteCommand :: Write { write, .. } ) ) => {
317+ self . record_send ( COMMAND , "backpressure" , started) ;
318+ self . record_backpressure ( COMMAND , "full" ) ;
319+ Err ( WriteError :: Backpressure ( write) )
320+ }
321+ Err ( mpsc:: error:: TrySendError :: Closed ( WriteCommand :: Write { .. } ) ) => {
322+ self . record_send ( COMMAND , "shutdown" , started) ;
323+ self . record_backpressure ( COMMAND , "closed" ) ;
324+ Err ( WriteError :: Shutdown )
325+ }
326+ Err ( _) => unreachable ! ( "sent a Write command" ) ,
327+ }
267328 }
268329
269330 /// Request a flush of the current delta.
@@ -273,18 +334,30 @@ impl<D: Delta> WriteCoordinatorHandle<D> {
273334 /// to guarantee durability, and the durable watermark will be advanced.
274335 /// Returns a handle that can be used to wait for the flush to complete.
275336 pub async fn flush ( & self , flush_storage : bool ) -> WriteResult < WriteHandle > {
337+ const COMMAND : & str = "flush" ;
338+ self . record_queue_depth ( ) ;
339+ let started = Instant :: now ( ) ;
276340 let ( tx, rx) = oneshot:: channel ( ) ;
277- self . write_tx
278- . try_send ( WriteCommand :: Flush {
279- epoch_tx : tx,
280- flush_storage,
281- } )
282- . map_err ( |e| match e {
283- mpsc:: error:: TrySendError :: Full ( _) => WriteError :: Backpressure ( ( ) ) ,
284- mpsc:: error:: TrySendError :: Closed ( _) => WriteError :: Shutdown ,
285- } ) ?;
286-
287- Ok ( WriteHandle :: new ( rx, self . watchers . clone ( ) ) )
341+ let send_result = self . write_tx . try_send ( WriteCommand :: Flush {
342+ epoch_tx : tx,
343+ flush_storage,
344+ } ) ;
345+ match send_result {
346+ Ok ( ( ) ) => {
347+ self . record_send ( COMMAND , "ok" , started) ;
348+ Ok ( WriteHandle :: new ( rx, self . watchers . clone ( ) ) )
349+ }
350+ Err ( mpsc:: error:: TrySendError :: Full ( _) ) => {
351+ self . record_send ( COMMAND , "backpressure" , started) ;
352+ self . record_backpressure ( COMMAND , "full" ) ;
353+ Err ( WriteError :: Backpressure ( ( ) ) )
354+ }
355+ Err ( mpsc:: error:: TrySendError :: Closed ( _) ) => {
356+ self . record_send ( COMMAND , "shutdown" , started) ;
357+ self . record_backpressure ( COMMAND , "closed" ) ;
358+ Err ( WriteError :: Shutdown )
359+ }
360+ }
288361 }
289362
290363 pub fn view ( & self ) -> Arc < View < D > > {
@@ -299,6 +372,7 @@ impl<D: Delta> WriteCoordinatorHandle<D> {
299372impl < D : Delta > Clone for WriteCoordinatorHandle < D > {
300373 fn clone ( & self ) -> Self {
301374 Self {
375+ name : self . name . clone ( ) ,
302376 write_tx : self . write_tx . clone ( ) ,
303377 watchers : self . watchers . clone ( ) ,
304378 view : self . view . clone ( ) ,
0 commit comments