@@ -9,7 +9,10 @@ use futures_util::{Stream, TryFutureExt};
99pub use http:: { self , Response } ;
1010use http_body:: Body ;
1111use lambda_runtime:: {
12- tower:: { util:: BoxCloneService , ServiceBuilder , ServiceExt } ,
12+ tower:: {
13+ util:: { BoxCloneService , MapRequest , MapResponse } ,
14+ ServiceBuilder , ServiceExt ,
15+ } ,
1316 Diagnostic ,
1417} ;
1518pub use lambda_runtime:: { Error , LambdaEvent , MetadataPrelude , Service , StreamResponse } ;
@@ -24,22 +27,10 @@ pub struct StreamAdapter<'a, S, B> {
2427 _phantom_data : PhantomData < & ' a B > ,
2528}
2629
27- impl < ' a , S , B > Clone for StreamAdapter < ' a , S , B >
28- where
29- S : Clone ,
30- {
31- fn clone ( & self ) -> Self {
32- Self {
33- service : self . service . clone ( ) ,
34- _phantom_data : PhantomData ,
35- }
36- }
37- }
38-
3930impl < ' a , S , B , E > From < S > for StreamAdapter < ' a , S , B >
4031where
41- S : Service < Request , Response = Response < B > , Error = E > + Clone + Send + ' static ,
42- S :: Future : Send + ' static ,
32+ S : Service < Request , Response = Response < B > , Error = E > ,
33+ S :: Future : Send + ' a ,
4334 B : Body + Unpin + Send + ' static ,
4435 B :: Data : Into < Bytes > + Send ,
4536 B :: Error : Into < Error > + Send + Debug ,
@@ -54,15 +45,15 @@ where
5445
5546impl < ' a , S , B , E > Service < LambdaEvent < LambdaRequest > > for StreamAdapter < ' a , S , B >
5647where
57- S : Service < Request , Response = Response < B > , Error = E > + Clone + Send + ' static ,
58- S :: Future : Send + ' static ,
48+ S : Service < Request , Response = Response < B > , Error = E > ,
49+ S :: Future : Send + ' a ,
5950 B : Body + Unpin + Send + ' static ,
6051 B :: Data : Into < Bytes > + Send ,
6152 B :: Error : Into < Error > + Send + Debug ,
6253{
6354 type Response = StreamResponse < BodyStream < B > > ;
6455 type Error = E ;
65- type Future = Pin < Box < dyn Future < Output = Result < Self :: Response , Self :: Error > > + Send + ' static > > ;
56+ type Future = Pin < Box < dyn Future < Output = Result < Self :: Response , Self :: Error > > + Send + ' a > > ;
6657
6758 fn poll_ready ( & mut self , cx : & mut Context < ' _ > ) -> Poll < Result < ( ) , Self :: Error > > {
6859 self . service . poll_ready ( cx)
8778/// Used internally by [`run_with_streaming_response`]; not part of the public
8879/// API.
8980#[ allow( clippy:: type_complexity) ]
90- fn into_stream_service < S , B , E > (
81+ fn into_stream_service < ' a , S , B , E > (
82+ handler : S ,
83+ ) -> MapResponse <
84+ MapRequest < S , impl FnMut ( LambdaEvent < LambdaRequest > ) -> Request > ,
85+ impl FnOnce ( Response < B > ) -> StreamResponse < BodyStream < B > > + Clone ,
86+ >
87+ where
88+ S : Service < Request , Response = Response < B > , Error = E > ,
89+ S :: Future : Send + ' a ,
90+ E : Debug + Into < Diagnostic > ,
91+ B : Body + Unpin + Send + ' static ,
92+ B :: Data : Into < Bytes > + Send ,
93+ B :: Error : Into < Error > + Send + Debug ,
94+ {
95+ ServiceBuilder :: new ( )
96+ . map_request ( event_to_request as fn ( LambdaEvent < LambdaRequest > ) -> Request )
97+ . service ( handler)
98+ . map_response ( into_stream_response)
99+ }
100+
101+ /// Builds a streaming-aware Tower service from a `Service<Request>` that can be
102+ /// cloned and sent across tasks. This is used by the concurrent HTTP entrypoint.
103+ #[ allow( dead_code) ]
104+ #[ allow( clippy:: type_complexity) ]
105+ fn into_stream_service_boxed < S , B , E > (
91106 handler : S ,
92107) -> BoxCloneService < LambdaEvent < LambdaRequest > , StreamResponse < BodyStream < B > > , E >
93108where
@@ -145,7 +160,26 @@ fn event_to_request(req: LambdaEvent<LambdaRequest>) -> Request {
145160///
146161/// [AWS docs for response streaming]:
147162/// https://docs.aws.amazon.com/lambda/latest/dg/configuration-response-streaming.html
148- pub async fn run_with_streaming_response < S , B , E > ( handler : S ) -> Result < ( ) , Error >
163+ pub async fn run_with_streaming_response < ' a , S , B , E > ( handler : S ) -> Result < ( ) , Error >
164+ where
165+ S : Service < Request , Response = Response < B > , Error = E > ,
166+ S :: Future : Send + ' a ,
167+ E : Debug + Into < Diagnostic > ,
168+ B : Body + Unpin + Send + ' static ,
169+ B :: Data : Into < Bytes > + Send ,
170+ B :: Error : Into < Error > + Send + Debug ,
171+ {
172+ lambda_runtime:: run ( into_stream_service ( handler) ) . await
173+ }
174+
175+ /// Runs the Lambda runtime with a handler that returns **streaming** HTTP
176+ /// responses, in a mode that is compatible with Lambda Managed Instances.
177+ ///
178+ /// This uses a cloneable, boxed service internally so it can be driven by the
179+ /// concurrent runtime. When `AWS_LAMBDA_MAX_CONCURRENCY` is not set or `<= 1`,
180+ /// it falls back to the same sequential behavior as [`run_with_streaming_response`].
181+ #[ allow( dead_code) ]
182+ pub async fn run_with_streaming_response_concurrent < S , B , E > ( handler : S ) -> Result < ( ) , Error >
149183where
150184 S : Service < Request , Response = Response < B > , Error = E > + Clone + Send + ' static ,
151185 S :: Future : Send + ' static ,
@@ -154,7 +188,7 @@ where
154188 B :: Data : Into < Bytes > + Send ,
155189 B :: Error : Into < Error > + Send + Debug ,
156190{
157- lambda_runtime:: run ( into_stream_service ( handler) ) . await
191+ lambda_runtime:: run_concurrent ( into_stream_service_boxed ( handler) ) . await
158192}
159193
160194pin_project_lite:: pin_project! {
0 commit comments