apalis_core/task/
metadata.rs1use crate::task::Task;
14use crate::task_fn::FromRequest;
15use std::ops::Deref;
16
17#[derive(Debug, Clone)]
19pub struct Meta<T>(pub T);
20
21impl<T> Deref for Meta<T> {
22 type Target = T;
23 fn deref(&self) -> &Self::Target {
24 &self.0
25 }
26}
27
28pub trait MetadataExt<T> {
31 type Error;
33 fn extract(&self) -> Result<T, Self::Error>;
35 fn inject(&mut self, value: T) -> Result<(), Self::Error>;
37}
38
39impl<T, Args: Send + Sync, Ctx: MetadataExt<T> + Send + Sync, IdType: Send + Sync>
40 FromRequest<Task<Args, Ctx, IdType>> for Meta<T>
41{
42 type Error = Ctx::Error;
43
44 async fn from_request(task: &Task<Args, Ctx, IdType>) -> Result<Self, Self::Error> {
45 task.parts.ctx.extract().map(Meta)
46 }
47}
48
49#[cfg(test)]
50#[allow(unused)]
51mod tests {
52 use std::{convert::Infallible, fmt::Debug, task::Poll, time::Duration};
53
54 use crate::{
55 error::BoxDynError,
56 task::{
57 Task,
58 metadata::{Meta, MetadataExt},
59 },
60 task_fn::FromRequest,
61 };
62 use futures_core::future::BoxFuture;
63 use tower::Service;
64
65 #[derive(Debug, Clone)]
66 struct ExampleService<S> {
67 service: S,
68 }
69 #[derive(Debug, Clone, Default)]
70 struct ExampleConfig {
71 timeout: Duration,
72 }
73
74 struct SampleStore;
75
76 impl MetadataExt<ExampleConfig> for SampleStore {
77 type Error = Infallible;
78 fn extract(&self) -> Result<ExampleConfig, Self::Error> {
79 Ok(ExampleConfig {
80 timeout: Duration::from_secs(1),
81 })
82 }
83 fn inject(&mut self, _: ExampleConfig) -> Result<(), Self::Error> {
84 unreachable!()
85 }
86 }
87
88 impl<S, Args: Send + Sync + 'static, Ctx: Send + Sync + 'static, IdType: Send + Sync + 'static>
89 Service<Task<Args, Ctx, IdType>> for ExampleService<S>
90 where
91 S: Service<Task<Args, Ctx, IdType>> + Clone + Send + 'static,
92 Ctx: MetadataExt<ExampleConfig> + Send,
93 Ctx::Error: Debug,
94 S::Future: Send + 'static,
95 {
96 type Response = S::Response;
97 type Error = S::Error;
98 type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
99
100 fn poll_ready(&mut self, cx: &mut std::task::Context<'_>) -> Poll<Result<(), Self::Error>> {
101 self.service.poll_ready(cx)
102 }
103
104 fn call(&mut self, request: Task<Args, Ctx, IdType>) -> Self::Future {
105 let mut svc = self.service.clone();
106
107 Box::pin(async move {
109 let _config: Meta<ExampleConfig> = request.extract().await.unwrap();
110 svc.call(request).await
111 })
112 }
113 }
114}