tower_scope_spawn/
layer.rs1use tower::Layer;
6
7use crate::service::ScopeSpawnService;
8
9#[derive(Copy, Clone, Debug, Default)]
11pub struct ScopeSpawnLayer {}
12
13impl ScopeSpawnLayer {
14 pub fn new() -> Self {
16 ScopeSpawnLayer {}
17 }
18}
19
20impl<S> Layer<S> for ScopeSpawnLayer {
21 type Service = ScopeSpawnService<S>;
22
23 fn layer(&self, service: S) -> Self::Service {
24 ScopeSpawnService::new(service)
25 }
26}
27
28#[cfg(test)]
29mod tests {
30 use axum::http::Request;
31 use bytes::Bytes;
32 use http_body_util::Empty;
33 use tower_test::mock;
34
35 use super::*;
36 use crate::service::ScopeFuture;
37
38 type TestRes = ();
41
42 #[tokio::test]
43 async fn test_cancellation_on_drop() {
44 let (mut mock_service, mut mock_handle) = mock::spawn_layer(ScopeSpawnLayer::new());
46
47 mock_handle.allow(1);
49
50 let req = Request::new(Empty::<Bytes>::new()); tokio_test::assert_ready_ok!(mock_service.poll_ready());
53 let fut: ScopeFuture<mock::future::ResponseFuture<TestRes>> = mock_service.call(req);
54
55 let (with_scope_req, _send_response) = mock_handle.next_request().await.unwrap();
57 let _inner_req = with_scope_req.request; let _inner_service_scope = with_scope_req.scope; let scope_from_fut = fut.scope();
62
63 let (tx, rx) = tokio::sync::oneshot::channel::<()>();
65 scope_from_fut.spawn(async move {
66 let _guard = tx; tokio::time::sleep(std::time::Duration::from_millis(200)).await;
68 });
69
70 drop(fut);
72
73 tokio::select! {
76 resp = rx => assert!(resp.is_err()),
77 _ = tokio::time::sleep(std::time::Duration::from_millis(100)) => {
78 panic!("Task should have been cancelled!");
79 }
80 }
81 }
82
83 #[tokio::test]
84 #[should_panic]
85 async fn test_no_cancellation_on_no_drop() {
86 let (mut mock_service, mut mock_handle) = mock::spawn_layer(ScopeSpawnLayer::new());
88
89 mock_handle.allow(1);
91
92 let req = Request::new(Empty::<Bytes>::new()); tokio_test::assert_ready_ok!(mock_service.poll_ready());
95 let fut: ScopeFuture<mock::future::ResponseFuture<TestRes>> = mock_service.call(req);
96
97 let (with_scope_req, _send_response) = mock_handle.next_request().await.unwrap();
99 let _inner_req = with_scope_req.request; let _inner_service_scope = with_scope_req.scope; let scope_from_fut = fut.scope();
104
105 let (tx, rx) = tokio::sync::oneshot::channel::<()>();
107 scope_from_fut.spawn(async move {
108 tokio::time::sleep(std::time::Duration::from_millis(200)).await;
109 let _ = tx.send(());
111 });
112
113 tokio::select! {
119 resp = rx => assert!(resp.is_err()),
120 _ = tokio::time::sleep(std::time::Duration::from_millis(100)) => {
121 panic!("Task was not cancelled!");
122 }
123 }
124 }
125}