1
- use lambda_runtime:: { Error , LambdaEvent , Service } ;
2
- use serde:: { Deserialize , Serialize } ;
3
1
use std:: {
4
2
future:: { ready, Future } ,
5
3
pin:: Pin ,
4
+ sync:: atomic:: { AtomicBool , Ordering } ,
6
5
} ;
6
+
7
+ use lambda_runtime:: { Error , LambdaEvent , Service } ;
8
+ use serde:: { Deserialize , Serialize } ;
7
9
use tracing:: info;
8
10
9
11
#[ derive( Deserialize , Debug ) ]
@@ -16,9 +18,30 @@ struct Response {
16
18
message : String ,
17
19
}
18
20
19
- #[ derive( Default ) ]
20
21
struct MyHandler {
21
22
invoke_count : usize ,
23
+ ready : AtomicBool ,
24
+ }
25
+
26
+ impl Default for MyHandler {
27
+ fn default ( ) -> Self {
28
+ Self {
29
+ invoke_count : usize:: default ( ) ,
30
+ // New instances are not ready to be called until polled.
31
+ ready : false . into ( ) ,
32
+ }
33
+ }
34
+ }
35
+
36
+ impl Clone for MyHandler {
37
+ fn clone ( & self ) -> Self {
38
+ Self {
39
+ invoke_count : self . invoke_count ,
40
+ // Cloned instances may not be immediately ready to be called.
41
+ // https://docs.rs/tower/0.4.13/tower/trait.Service.html#be-careful-when-cloning-inner-services
42
+ ready : false . into ( ) ,
43
+ }
44
+ }
22
45
}
23
46
24
47
impl Service < LambdaEvent < Request > > for MyHandler {
@@ -27,12 +50,30 @@ impl Service<LambdaEvent<Request>> for MyHandler {
27
50
type Response = Response ;
28
51
29
52
fn poll_ready ( & mut self , _cx : & mut core:: task:: Context < ' _ > ) -> core:: task:: Poll < Result < ( ) , Self :: Error > > {
53
+ if self . ready . swap ( true , Ordering :: SeqCst ) {
54
+ info ! ( "[runtime-trait] Service was already ready" ) ;
55
+ } else {
56
+ info ! ( "[runtime-trait] Service is now ready" ) ;
57
+ } ;
58
+
30
59
core:: task:: Poll :: Ready ( Ok ( ( ) ) )
31
60
}
32
61
33
62
fn call ( & mut self , request : LambdaEvent < Request > ) -> Self :: Future {
34
63
self . invoke_count += 1 ;
35
- info ! ( "[handler] Received event {}: {:?}" , self . invoke_count, request) ;
64
+ info ! ( "[runtime-trait] Received event {}: {:?}" , self . invoke_count, request) ;
65
+
66
+ // After being called once, the service is no longer ready until polled again.
67
+ if self . ready . swap ( false , Ordering :: SeqCst ) {
68
+ info ! ( "[runtime-trait] The service is ready" ) ;
69
+ } else {
70
+ // https://docs.rs/tower/latest/tower/trait.Service.html#backpressure
71
+ // https://docs.rs/tower/latest/tower/trait.Service.html#be-careful-when-cloning-inner-services
72
+ // > Services are permitted to panic if `call` is invoked without obtaining
73
+ // > `Poll::Ready(Ok(()))` from `poll_ready`.
74
+ panic ! ( "[runtime-trait] The service is not ready; `.poll_ready()` must be called first" ) ;
75
+ }
76
+
36
77
Box :: pin ( ready ( Ok ( Response {
37
78
message : request. payload . command . to_uppercase ( ) ,
38
79
} ) ) )
0 commit comments