@@ -37,6 +37,7 @@ enum Target {
3737 } ,
3838 Channel {
3939 channel : String ,
40+ reply_timeout_ms : Option < u64 > ,
4041 } ,
4142}
4243
@@ -89,8 +90,12 @@ impl Route {
8990 body : body. clone ( ) ,
9091 }
9192 }
92- RouteTarget :: Channel { channel } => Target :: Channel {
93+ RouteTarget :: Channel {
94+ channel,
95+ reply_timeout_ms,
96+ } => Target :: Channel {
9397 channel : channel. clone ( ) ,
98+ reply_timeout_ms : * reply_timeout_ms,
9499 } ,
95100 } ;
96101
@@ -167,7 +172,13 @@ impl Router {
167172 self . invoke_component ( component, function, body. as_deref ( ) , params, req)
168173 . await
169174 }
170- Target :: Channel { channel } => self . publish_to_channel ( channel, req) . await ,
175+ Target :: Channel {
176+ channel,
177+ reply_timeout_ms,
178+ } => {
179+ self . publish_to_channel ( channel, req, * reply_timeout_ms)
180+ . await
181+ }
171182 }
172183 }
173184
@@ -346,6 +357,7 @@ impl Router {
346357 & self ,
347358 channel : & str ,
348359 req : Request < Incoming > ,
360+ reply_timeout_ms : Option < u64 > ,
349361 ) -> Response < Full < Bytes > > {
350362 let publisher = match & self . publisher {
351363 Some ( p) => p,
@@ -379,17 +391,61 @@ impl Router {
379391 let mut headers = HashMap :: new ( ) ;
380392 headers. insert ( "content-type" . to_string ( ) , content_type) ;
381393
382- match publisher. publish ( channel, body_bytes, headers) . await {
383- Ok ( ( ) ) => Response :: builder ( )
384- . status ( StatusCode :: ACCEPTED )
385- . body ( Full :: new ( Bytes :: new ( ) ) )
386- . unwrap ( ) ,
387- Err ( e) => Response :: builder ( )
388- . status ( StatusCode :: INTERNAL_SERVER_ERROR )
389- . body ( Full :: new ( Bytes :: from ( format ! (
390- "failed to publish to channel '{channel}': {e}"
391- ) ) ) )
392- . unwrap ( ) ,
394+ match reply_timeout_ms {
395+ None => match publisher. publish ( channel, body_bytes, headers) . await {
396+ Ok ( ( ) ) => Response :: builder ( )
397+ . status ( StatusCode :: ACCEPTED )
398+ . body ( Full :: new ( Bytes :: new ( ) ) )
399+ . unwrap ( ) ,
400+ Err ( e) => Response :: builder ( )
401+ . status ( StatusCode :: INTERNAL_SERVER_ERROR )
402+ . body ( Full :: new ( Bytes :: from ( format ! (
403+ "failed to publish to channel '{channel}': {e}"
404+ ) ) ) )
405+ . unwrap ( ) ,
406+ } ,
407+ Some ( timeout_ms) => {
408+ let handle = match publisher
409+ . publish_request ( channel, body_bytes, headers)
410+ . await
411+ {
412+ Ok ( h) => h,
413+ Err ( e) => {
414+ return Response :: builder ( )
415+ . status ( StatusCode :: INTERNAL_SERVER_ERROR )
416+ . body ( Full :: new ( Bytes :: from ( format ! (
417+ "failed to publish to channel '{channel}': {e}"
418+ ) ) ) )
419+ . unwrap ( ) ;
420+ }
421+ } ;
422+
423+ let timeout = std:: time:: Duration :: from_millis ( timeout_ms) ;
424+ match tokio:: time:: timeout ( timeout, handle. take ( ) ) . await {
425+ Ok ( Ok ( reply) ) => {
426+ let reply_content_type = reply
427+ . headers ( )
428+ . content_type ( )
429+ . unwrap_or ( "application/octet-stream" )
430+ . to_string ( ) ;
431+ Response :: builder ( )
432+ . status ( StatusCode :: OK )
433+ . header ( "content-type" , reply_content_type)
434+ . body ( Full :: new ( Bytes :: copy_from_slice ( reply. body ( ) ) ) )
435+ . unwrap ( )
436+ }
437+ Ok ( Err ( e) ) => Response :: builder ( )
438+ . status ( StatusCode :: INTERNAL_SERVER_ERROR )
439+ . body ( Full :: new ( Bytes :: from ( format ! ( "reply error: {e}" ) ) ) )
440+ . unwrap ( ) ,
441+ Err ( _) => Response :: builder ( )
442+ . status ( StatusCode :: GATEWAY_TIMEOUT )
443+ . body ( Full :: new ( Bytes :: from ( format ! (
444+ "no reply received within {timeout_ms}ms"
445+ ) ) ) )
446+ . unwrap ( ) ,
447+ }
448+ }
393449 }
394450 }
395451}
0 commit comments