1use std::marker::PhantomData;
2
3use futures::Stream;
4use tower::{
5 layer::util::{Identity, Stack},
6 Layer, Service, ServiceBuilder,
7};
8
9use crate::{
10 backend::Backend,
11 error::Error,
12 layers::extensions::Data,
13 request::Request,
14 service_fn::service_fn,
15 service_fn::ServiceFn,
16 worker::{Ready, Worker, WorkerId},
17};
18
19pub struct WorkerBuilder<Req, Ctx, Source, Middleware, Serv> {
22 pub(crate) id: WorkerId,
23 pub(crate) request: PhantomData<Request<Req, Ctx>>,
24 pub(crate) layer: ServiceBuilder<Middleware>,
25 pub(crate) source: Source,
26 service: PhantomData<Serv>,
27}
28
29impl<Req, Ctx, Source, Middleware, Serv> std::fmt::Debug
30 for WorkerBuilder<Req, Ctx, Source, Middleware, Serv>
31{
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 f.debug_struct("WorkerBuilder")
34 .field("id", &self.id)
35 .field("job", &std::any::type_name::<Req>())
36 .field("layer", &std::any::type_name::<Middleware>())
37 .field("source", &std::any::type_name::<Source>())
38 .finish()
39 }
40}
41
42impl<Serv> WorkerBuilder<(), (), (), Identity, Serv> {
43 pub fn new<T: AsRef<str>>(name: T) -> WorkerBuilder<(), (), (), Identity, Serv> {
45 let job: PhantomData<Request<(), ()>> = PhantomData;
46 WorkerBuilder {
47 request: job,
48 layer: ServiceBuilder::new(),
49 source: (),
50 id: WorkerId::new(name),
51 service: PhantomData,
52 }
53 }
54}
55
56impl<M, Serv> WorkerBuilder<(), (), (), M, Serv> {
57 #[deprecated(since = "0.6.0", note = "Consider using the `.backend`")]
59 pub fn stream<
60 NS: Stream<Item = Result<Option<Request<NJ, Ctx>>, Error>> + Send + 'static,
61 NJ,
62 Ctx,
63 >(
64 self,
65 stream: NS,
66 ) -> WorkerBuilder<NJ, Ctx, NS, M, Serv> {
67 WorkerBuilder {
68 request: PhantomData,
69 layer: self.layer,
70 source: stream,
71 id: self.id,
72 service: self.service,
73 }
74 }
75
76 pub fn backend<NB: Backend<Request<NJ, Ctx>>, NJ, Res: Send, Ctx>(
78 self,
79 backend: NB,
80 ) -> WorkerBuilder<NJ, Ctx, NB, M, Serv>
81 where
82 Serv: Service<Request<NJ, Ctx>, Response = Res>,
83 {
84 WorkerBuilder {
85 request: PhantomData,
86 layer: self.layer,
87 source: backend,
88 id: self.id,
89 service: self.service,
90 }
91 }
92}
93
94impl<Req, M, Serv, Ctx> WorkerBuilder<Req, Ctx, (), M, Serv> {
95 pub fn chain<NewLayer>(
98 self,
99 f: impl FnOnce(ServiceBuilder<M>) -> ServiceBuilder<NewLayer>,
100 ) -> WorkerBuilder<Req, Ctx, (), NewLayer, Serv> {
101 let middleware = f(self.layer);
102
103 WorkerBuilder {
104 request: self.request,
105 layer: middleware,
106 id: self.id,
107 source: self.source,
108 service: self.service,
109 }
110 }
111 pub fn layer<U>(self, layer: U) -> WorkerBuilder<Req, Ctx, (), Stack<U, M>, Serv>
113 where
114 M: Layer<U>,
115 {
116 WorkerBuilder {
117 request: self.request,
118 source: self.source,
119 layer: self.layer.layer(layer),
120 id: self.id,
121 service: self.service,
122 }
123 }
124
125 pub fn data<D>(self, data: D) -> WorkerBuilder<Req, Ctx, (), Stack<Data<D>, M>, Serv>
128 where
129 M: Layer<Data<D>>,
130 {
131 WorkerBuilder {
132 request: self.request,
133 source: self.source,
134 layer: self.layer.layer(Data::new(data)),
135 id: self.id,
136 service: self.service,
137 }
138 }
139}
140
141impl<Req, P, M, S, Ctx> WorkerFactory<Req, Ctx, S> for WorkerBuilder<Req, Ctx, P, M, S>
142where
143 S: Service<Request<Req, Ctx>>,
144 M: Layer<S>,
145 P: Backend<Request<Req, Ctx>>,
146{
147 type Source = P;
148
149 type Service = M::Service;
150
151 fn build(self, service: S) -> Worker<Ready<M::Service, P>> {
152 let worker_id = self.id;
153 let poller = self.source;
154 let middleware = self.layer;
155 let service = middleware.service(service);
156
157 Worker::new(worker_id, Ready::new(service, poller))
158 }
159}
160pub trait WorkerFactory<Req, Ctx, S> {
162 type Source;
164
165 type Service;
167 fn build(self, service: S) -> Worker<Ready<Self::Service, Self::Source>>;
176}
177
178pub trait WorkerFactoryFn<Req, Ctx, F, FnArgs> {
180 type Source;
182
183 type Service;
185 fn build_fn(self, f: F) -> Worker<Ready<Self::Service, Self::Source>>;
216}
217
218impl<Req, W, F, Ctx, FnArgs> WorkerFactoryFn<Req, Ctx, F, FnArgs> for W
219where
220 W: WorkerFactory<Req, Ctx, ServiceFn<F, Req, Ctx, FnArgs>>,
221{
222 type Source = W::Source;
223
224 type Service = W::Service;
225
226 fn build_fn(self, f: F) -> Worker<Ready<Self::Service, Self::Source>> {
227 self.build(service_fn(f))
228 }
229}