Skip to main content

tower_scope_spawn/
lib.rs

1//!
2//! Provide task management to tower services.
3//!
4//! A Simple Example
5//!
6//! ```rust
7//! //! An example of how to use the `ScopeSpawnLayer`.
8//! use std::convert::Infallible;
9//! use std::future::Future;
10//! use std::pin::Pin;
11//! use std::task::Context;
12//! use std::task::Poll;
13//! use std::time::Duration;
14//!
15//! use bytes::Bytes;
16//! use http_body_util::BodyExt;
17//! use http_body_util::Empty;
18//! use hyper::server::conn::http1;
19//! use hyper::Request;
20//! use hyper::Response;
21//! use hyper_util::rt::TokioIo;
22//! use hyper_util::service::TowerToHyperService;
23//! use tokio::net::TcpListener;
24//! use tokio::time::sleep;
25//! use tower::Service;
26//! use tower::ServiceBuilder;
27//!
28//! use tower_scope_spawn::layer::ScopeSpawnLayer;
29//! use tower_scope_spawn::service::WithScope;
30//!
31//! // A simple tower::Service that processes a request and spawns a background task.
32//! #[derive(Clone)]
33//! struct MyTowerService;
34//!
35//! impl Service<WithScope<Request<hyper::body::Incoming>>> for MyTowerService {
36//!     type Response = Response<Empty<Bytes>>;
37//!     type Error = Infallible;
38//!     type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
39//!
40//!     fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
41//!         Poll::Ready(Ok(()))
42//!     }
43//!
44//!     fn call(&mut self, req: WithScope<Request<hyper::body::Incoming>>) -> Self::Future {
45//!         let scope = req.scope;
46//!         let _original_request = req.request;
47//!
48//!         Box::pin(async move {
49//!             println!("[Handler] Received request. Spawning background task.");
50//!
51//!             // Here, we use spawn_with_hooks to clearly see the outcome.
52//!             scope.spawn_with_hooks(
53//!                 async move {
54//!                     // This task will be cancelled if the request is dropped.
55//!                     for i in 1..=5 {
56//!                         println!("[Background] Working... step {} of 5", i);
57//!                         sleep(Duration::from_millis(500)).await;
58//!                     }
59//!                 },
60//!                 || println!("[Background] Task finished normally."),
61//!                 || println!("[Background] Task was cancelled."),
62//!             );
63//!
64//!             // The handler waits for 3 seconds before sending a response.
65//!             // If the user presses Ctrl+C, then they'll seek the task is cancelled.
66//!             sleep(Duration::from_secs(3)).await;
67//!             println!("[Handler] Sending response.");
68//!             Ok(Response::new(Empty::new()))
69//!         })
70//!     }
71//! }
72//!
73#![warn(
74    missing_docs,
75    missing_debug_implementations,
76    missing_copy_implementations,
77    trivial_casts,
78    trivial_numeric_casts,
79    unsafe_code,
80    unstable_features,
81    unused_import_braces,
82    unused_qualifications
83)]
84
85pub mod layer;
86pub mod service;