1use super::{BootApplication, BootApplicationBuilder};
2use crate::{BoxFuture, HttpAdapter, MessageTransport, Module, ModuleRef, Result};
3use std::net::SocketAddr;
4use std::sync::Arc;
5
6pub struct BootFactory;
8
9impl BootFactory {
10 pub fn create<M>(module: M) -> Result<BootApplicationHandle>
11 where
12 M: Module,
13 {
14 Self::create_with_builder(BootApplication::builder().import(module))
15 }
16
17 pub fn create_arc(module: Arc<dyn Module>) -> Result<BootApplicationHandle> {
18 Self::create_with_builder(BootApplication::builder().import_arc(module))
19 }
20
21 pub fn create_with_builder(builder: BootApplicationBuilder) -> Result<BootApplicationHandle> {
22 Ok(BootApplicationHandle::from_app(builder.build()?))
23 }
24
25 pub async fn create_async<M>(module: M) -> Result<BootApplicationHandle>
26 where
27 M: Module,
28 {
29 Self::create_with_builder_async(BootApplication::builder().import(module)).await
30 }
31
32 pub async fn create_arc_async(module: Arc<dyn Module>) -> Result<BootApplicationHandle> {
33 Self::create_with_builder_async(BootApplication::builder().import_arc(module)).await
34 }
35
36 pub async fn create_with_builder_async(
37 builder: BootApplicationBuilder,
38 ) -> Result<BootApplicationHandle> {
39 Ok(BootApplicationHandle::from_app(
40 builder.build_async().await?,
41 ))
42 }
43
44 pub fn create_application_context<M>(module: M) -> Result<BootApplicationContext>
45 where
46 M: Module,
47 {
48 Self::create_application_context_with_builder(BootApplication::builder().import(module))
49 }
50
51 pub fn create_application_context_arc(
52 module: Arc<dyn Module>,
53 ) -> Result<BootApplicationContext> {
54 Self::create_application_context_with_builder(BootApplication::builder().import_arc(module))
55 }
56
57 pub fn create_application_context_with_builder(
58 builder: BootApplicationBuilder,
59 ) -> Result<BootApplicationContext> {
60 Ok(BootApplicationContext {
61 handle: Self::create_with_builder(builder)?,
62 })
63 }
64
65 pub async fn create_application_context_async<M>(module: M) -> Result<BootApplicationContext>
66 where
67 M: Module,
68 {
69 Self::create_application_context_with_builder_async(
70 BootApplication::builder().import(module),
71 )
72 .await
73 }
74
75 pub async fn create_application_context_arc_async(
76 module: Arc<dyn Module>,
77 ) -> Result<BootApplicationContext> {
78 Self::create_application_context_with_builder_async(
79 BootApplication::builder().import_arc(module),
80 )
81 .await
82 }
83
84 pub async fn create_application_context_with_builder_async(
85 builder: BootApplicationBuilder,
86 ) -> Result<BootApplicationContext> {
87 Ok(BootApplicationContext {
88 handle: Self::create_with_builder_async(builder).await?,
89 })
90 }
91
92 pub fn create_microservice<M, T>(module: M, transport: T) -> Result<BootMicroservice<T>>
93 where
94 M: Module,
95 T: MessageTransport,
96 {
97 Self::create_microservice_with_builder(BootApplication::builder().import(module), transport)
98 }
99
100 pub fn create_microservice_with_builder<T>(
101 builder: BootApplicationBuilder,
102 transport: T,
103 ) -> Result<BootMicroservice<T>>
104 where
105 T: MessageTransport,
106 {
107 Ok(BootMicroservice::new(builder.build()?, transport))
108 }
109
110 pub async fn create_microservice_async<M, T>(
111 module: M,
112 transport: T,
113 ) -> Result<BootMicroservice<T>>
114 where
115 M: Module,
116 T: MessageTransport,
117 {
118 Self::create_microservice_with_builder_async(
119 BootApplication::builder().import(module),
120 transport,
121 )
122 .await
123 }
124
125 pub async fn create_microservice_with_builder_async<T>(
126 builder: BootApplicationBuilder,
127 transport: T,
128 ) -> Result<BootMicroservice<T>>
129 where
130 T: MessageTransport,
131 {
132 Ok(BootMicroservice::new(
133 builder.build_async().await?,
134 transport,
135 ))
136 }
137}
138
139pub struct BootApplicationHandle {
141 app: BootApplication,
142 initialized: bool,
143 microservices: Vec<Box<dyn ConnectedMicroservice>>,
144}
145
146impl BootApplicationHandle {
147 pub fn from_app(app: BootApplication) -> Self {
148 Self {
149 app,
150 initialized: false,
151 microservices: Vec::new(),
152 }
153 }
154
155 pub fn app(&self) -> &BootApplication {
156 &self.app
157 }
158
159 pub fn module_ref(&self) -> &ModuleRef {
160 self.app.module_ref()
161 }
162
163 pub fn into_app(self) -> BootApplication {
164 self.app
165 }
166
167 pub fn get<T>(&self) -> Result<Arc<T>>
168 where
169 T: Send + Sync + 'static,
170 {
171 self.app.get::<T>()
172 }
173
174 pub fn get_named<T>(&self, token: &str) -> Result<Arc<T>>
175 where
176 T: Send + Sync + 'static,
177 {
178 self.app.get_named::<T>(token)
179 }
180
181 pub fn get_optional<T>(&self) -> Result<Option<Arc<T>>>
182 where
183 T: Send + Sync + 'static,
184 {
185 self.app.get_optional::<T>()
186 }
187
188 pub fn get_optional_named<T>(&self, token: &str) -> Result<Option<Arc<T>>>
189 where
190 T: Send + Sync + 'static,
191 {
192 self.app.get_optional_named::<T>(token)
193 }
194
195 pub fn is_initialized(&self) -> bool {
196 self.initialized
197 }
198
199 pub async fn init(&mut self) -> Result<()> {
200 if self.initialized {
201 return Ok(());
202 }
203
204 if let Err(error) = self.app.bootstrap().await {
205 let _ = self.app.shutdown().await;
206 return Err(error);
207 }
208
209 self.initialized = true;
210 Ok(())
211 }
212
213 pub async fn close(&mut self) -> Result<()> {
214 if !self.initialized {
215 return Ok(());
216 }
217
218 self.app.shutdown().await?;
219 self.initialized = false;
220 Ok(())
221 }
222
223 pub async fn listen_with<A>(&mut self, adapter: &A, addr: SocketAddr) -> Result<()>
224 where
225 A: HttpAdapter,
226 {
227 self.init().await?;
228 let serve_result = adapter.serve(self.app.clone(), addr).await;
229 let close_result = self.close().await;
230
231 match (serve_result, close_result) {
232 (Err(error), _) => Err(error),
233 (Ok(()), Err(error)) => Err(error),
234 (Ok(()), Ok(())) => Ok(()),
235 }
236 }
237
238 pub fn connect_microservice<T>(&mut self, transport: T) -> usize
239 where
240 T: MessageTransport + Send + Sync + 'static,
241 {
242 let index = self.microservices.len();
243 self.microservices
244 .push(Box::new(ConnectedMessageTransport { transport }));
245 index
246 }
247
248 pub fn connected_microservice_count(&self) -> usize {
249 self.microservices.len()
250 }
251
252 pub async fn start_all_microservices(&mut self) -> Result<()> {
253 self.init().await?;
254 for microservice in &self.microservices {
255 microservice.serve(self.app.clone()).await?;
256 }
257 Ok(())
258 }
259}
260
261pub struct BootApplicationContext {
263 handle: BootApplicationHandle,
264}
265
266impl BootApplicationContext {
267 pub fn app(&self) -> &BootApplication {
268 self.handle.app()
269 }
270
271 pub fn module_ref(&self) -> &ModuleRef {
272 self.handle.module_ref()
273 }
274
275 pub fn into_app(self) -> BootApplication {
276 self.handle.into_app()
277 }
278
279 pub fn get<T>(&self) -> Result<Arc<T>>
280 where
281 T: Send + Sync + 'static,
282 {
283 self.handle.get::<T>()
284 }
285
286 pub fn get_named<T>(&self, token: &str) -> Result<Arc<T>>
287 where
288 T: Send + Sync + 'static,
289 {
290 self.handle.get_named::<T>(token)
291 }
292
293 pub fn get_optional<T>(&self) -> Result<Option<Arc<T>>>
294 where
295 T: Send + Sync + 'static,
296 {
297 self.handle.get_optional::<T>()
298 }
299
300 pub fn get_optional_named<T>(&self, token: &str) -> Result<Option<Arc<T>>>
301 where
302 T: Send + Sync + 'static,
303 {
304 self.handle.get_optional_named::<T>(token)
305 }
306
307 pub fn is_initialized(&self) -> bool {
308 self.handle.is_initialized()
309 }
310
311 pub async fn init(&mut self) -> Result<()> {
312 self.handle.init().await
313 }
314
315 pub async fn close(&mut self) -> Result<()> {
316 self.handle.close().await
317 }
318}
319
320pub struct BootMicroservice<T> {
322 app: BootApplication,
323 transport: T,
324 initialized: bool,
325}
326
327impl<T> BootMicroservice<T>
328where
329 T: MessageTransport,
330{
331 pub fn new(app: BootApplication, transport: T) -> Self {
332 Self {
333 app,
334 transport,
335 initialized: false,
336 }
337 }
338
339 pub fn app(&self) -> &BootApplication {
340 &self.app
341 }
342
343 pub fn transport(&self) -> &T {
344 &self.transport
345 }
346
347 pub fn into_app(self) -> BootApplication {
348 self.app
349 }
350
351 pub fn build_client(&self) -> Result<T::Output> {
352 self.transport.build(self.app.clone())
353 }
354
355 pub fn is_initialized(&self) -> bool {
356 self.initialized
357 }
358
359 pub async fn init(&mut self) -> Result<()> {
360 if self.initialized {
361 return Ok(());
362 }
363
364 if let Err(error) = self.app.bootstrap().await {
365 let _ = self.app.shutdown().await;
366 return Err(error);
367 }
368
369 self.initialized = true;
370 Ok(())
371 }
372
373 pub async fn close(&mut self) -> Result<()> {
374 if !self.initialized {
375 return Ok(());
376 }
377
378 self.app.shutdown().await?;
379 self.initialized = false;
380 Ok(())
381 }
382
383 pub async fn listen(&mut self) -> Result<()> {
384 self.init().await?;
385 let serve_result = self.transport.serve(self.app.clone()).await;
386 let close_result = self.close().await;
387
388 match (serve_result, close_result) {
389 (Err(error), _) => Err(error),
390 (Ok(()), Err(error)) => Err(error),
391 (Ok(()), Ok(())) => Ok(()),
392 }
393 }
394}
395
396trait ConnectedMicroservice: Send + Sync {
397 fn serve(&self, app: BootApplication) -> BoxFuture<'static, Result<()>>;
398}
399
400struct ConnectedMessageTransport<T> {
401 transport: T,
402}
403
404impl<T> ConnectedMicroservice for ConnectedMessageTransport<T>
405where
406 T: MessageTransport + Send + Sync + 'static,
407{
408 fn serve(&self, app: BootApplication) -> BoxFuture<'static, Result<()>> {
409 self.transport.serve(app)
410 }
411}