@@ -319,12 +319,13 @@ impl<Exe: Executor> ConnectionSender<Exe> {
319319 }
320320
321321 #[ cfg_attr( feature = "telemetry" , tracing:: instrument( skip_all) ) ]
322- pub ( crate ) fn send (
322+ pub ( crate ) async fn send (
323323 & self ,
324324 producer_id : u64 ,
325325 producer_name : String ,
326326 sequence_id : u64 ,
327327 message : producer:: ProducerMessage ,
328+ block_if_queue_full : bool ,
328329 ) -> Result <
329330 impl Future < Output = Result < proto:: CommandSendReceipt , ConnectionError > > ,
330331 ConnectionError ,
@@ -334,7 +335,13 @@ impl<Exe: Executor> ConnectionSender<Exe> {
334335 sequence_id,
335336 } ;
336337 let msg = messages:: send ( producer_id, producer_name, sequence_id, message) ;
337- self . send_message_non_blocking ( msg, key, |resp| resp. command . send_receipt )
338+ self . send_message_non_blocking (
339+ msg,
340+ key,
341+ |resp| resp. command . send_receipt ,
342+ block_if_queue_full,
343+ )
344+ . await
338345 }
339346
340347 #[ cfg_attr( feature = "telemetry" , tracing:: instrument( skip_all) ) ]
@@ -633,15 +640,22 @@ impl<Exe: Executor> ConnectionSender<Exe> {
633640 where
634641 F : FnOnce ( Message ) -> Option < R > + ' static ,
635642 {
636- self . send_message_non_blocking ( msg, key, extract) ?. await
643+ // This method is called for RPCs other than CommandSend. If the queue is full due to too
644+ // many CommandSend RPCs not processed in time, we should wait rather than fail fast
645+ // because it's a client side issue that can be recovered later. Hence, set
646+ // block_if_queue_full to true here.
647+ self . send_message_non_blocking ( msg, key, extract, true )
648+ . await ?
649+ . await
637650 }
638651
639652 #[ cfg_attr( feature = "telemetry" , tracing:: instrument( skip_all) ) ]
640- fn send_message_non_blocking < R : Debug , F > (
653+ async fn send_message_non_blocking < R : Debug , F > (
641654 & self ,
642655 msg : Message ,
643656 key : RequestKey ,
644657 extract : F ,
658+ block_if_queue_full : bool ,
645659 ) -> Result < impl Future < Output = Result < R , ConnectionError > > , ConnectionError >
646660 where
647661 F : FnOnce ( Message ) -> Option < R > + ' static ,
@@ -668,62 +682,76 @@ impl<Exe: Executor> ConnectionSender<Exe> {
668682 } ) ?
669683 } ;
670684
671- match (
672- self . registrations
673- . unbounded_send ( Register :: Request { key, resolver } ) ,
674- self . tx . try_send ( msg) ,
675- ) {
676- ( Ok ( _) , Ok ( _) ) => {
677- let connection_id = self . connection_id ;
678- let error = self . error . clone ( ) ;
679- let delay_f = self . executor . delay ( self . operation_timeout ) ;
680- trace ! (
681- "Create timeout futures with operation timeout at {:?}" ,
682- self . operation_timeout
685+ self . registrations
686+ . unbounded_send ( Register :: Request { key, resolver } )
687+ . map_err ( |e| {
688+ warn ! (
689+ "connection {} disconnected when sending the Request: {}" ,
690+ self . connection_id, e
683691 ) ;
684- let fut = async move {
685- pin_mut ! ( response) ;
686- pin_mut ! ( delay_f) ;
687- match select ( response, delay_f) . await {
688- Either :: Left ( ( res, _) ) => {
689- debug ! ( "Received response: {:?}" , res) ;
690- res
691- }
692- Either :: Right ( _) => {
693- warn ! (
694- "connection {} timedout sending message to the Pulsar server" ,
695- connection_id
696- ) ;
697- error. set ( ConnectionError :: Io ( std:: io:: Error :: new (
698- std:: io:: ErrorKind :: TimedOut ,
699- format ! (
700- " connection {} timedout sending message to the Pulsar server" ,
701- connection_id
702- ) ,
703- ) ) ) ;
704- Err ( ConnectionError :: Io ( std:: io:: Error :: new (
705- std:: io:: ErrorKind :: TimedOut ,
706- format ! (
707- " connection {} timedout sending message to the Pulsar server" ,
708- connection_id
709- ) ,
710- ) ) )
711- }
712- }
713- } ;
714-
715- Ok ( fut)
716- }
717- ( _, Err ( e) ) if e. is_full ( ) => Err ( ConnectionError :: SlowDown ) ,
718- _ => {
692+ ConnectionError :: Disconnected
693+ } ) ?;
694+ if block_if_queue_full {
695+ self . tx . send ( msg) . await . map_err ( |e| {
719696 warn ! (
720- "connection {} disconnected sending message to the Pulsar server " ,
721- self . connection_id
697+ "connection {} disconnected when sending the message: {} " ,
698+ self . connection_id, e
722699 ) ;
723- self . error . set ( ConnectionError :: Disconnected ) ;
724- Err ( ConnectionError :: Disconnected )
700+ ConnectionError :: Disconnected
701+ } ) ?;
702+ } else {
703+ self . tx . try_send ( msg) . map_err ( |e| {
704+ if e. is_full ( ) {
705+ ConnectionError :: SlowDown
706+ } else {
707+ warn ! (
708+ "connection {} disconnected when sending the message: {}" ,
709+ self . connection_id, e
710+ ) ;
711+ ConnectionError :: Disconnected
712+ }
713+ } ) ?;
714+ } ;
715+
716+ let connection_id = self . connection_id ;
717+ let error = self . error . clone ( ) ;
718+ let delay_f = self . executor . delay ( self . operation_timeout ) ;
719+ trace ! (
720+ "Create timeout futures with operation timeout at {:?}" ,
721+ self . operation_timeout
722+ ) ;
723+ let fut = async move {
724+ pin_mut ! ( response) ;
725+ pin_mut ! ( delay_f) ;
726+ match select ( response, delay_f) . await {
727+ Either :: Left ( ( res, _) ) => {
728+ debug ! ( "Received response: {:?}" , res) ;
729+ res
730+ }
731+ Either :: Right ( _) => {
732+ warn ! (
733+ "connection {} timedout sending message to the Pulsar server" ,
734+ connection_id
735+ ) ;
736+ error. set ( ConnectionError :: Io ( std:: io:: Error :: new (
737+ std:: io:: ErrorKind :: TimedOut ,
738+ format ! (
739+ " connection {} timedout sending message to the Pulsar server" ,
740+ connection_id
741+ ) ,
742+ ) ) ) ;
743+ Err ( ConnectionError :: Io ( std:: io:: Error :: new (
744+ std:: io:: ErrorKind :: TimedOut ,
745+ format ! (
746+ " connection {} timedout sending message to the Pulsar server" ,
747+ connection_id
748+ ) ,
749+ ) ) )
750+ }
725751 }
726- }
752+ } ;
753+
754+ Ok ( fut)
727755 }
728756
729757 /// wait for desired message(commandproducersuccess with ready field true)
0 commit comments