1use crate::{
2 BoxFuture, Container, Controller, EventHandler, EventHandlerDef, Injectable, MessageHandlerDef,
3 MessageHandlerKind, Microservice, MicroserviceDef, RegisterableEventHandler, Result,
4 WebSocketGateway,
5};
6use std::{
7 any::{Any, TypeId},
8 collections::{HashMap, HashSet},
9 fmt::Debug,
10 future::Future,
11 sync::Arc,
12 time::Instant,
13};
14
15type ProviderValue = Arc<dyn Any + Send + Sync>;
16type BuildProviderFn =
17 Box<dyn for<'a> Fn(&'a Container) -> BoxFuture<'a, crate::Result<ProviderValue>> + Send + Sync>;
18type LifecycleFn =
19 Box<dyn for<'a> Fn(&'a ProviderValue) -> BoxFuture<'a, crate::Result<()>> + Send + Sync>;
20
21#[derive(Clone, Copy)]
23pub struct ProviderDependency {
25 type_id: TypeId,
26 type_name: &'static str,
27}
28
29impl ProviderDependency {
30 pub fn of<T: Send + Sync + 'static>() -> Self {
32 Self {
33 type_id: TypeId::of::<T>(),
34 type_name: std::any::type_name::<T>(),
35 }
36 }
37
38 pub(crate) fn type_id(&self) -> TypeId {
39 self.type_id
40 }
41}
42
43#[macro_export]
51macro_rules! provider_dependencies {
52 ($($dependency:ty),* $(,)?) => {
53 vec![$($crate::ProviderDependency::of::<$dependency>()),*]
54 };
55}
56
57pub struct ProviderDef {
59 type_id: TypeId,
60 type_name: &'static str,
61 dependencies: Vec<ProviderDependency>,
62 build: BuildProviderFn,
63 init_fn: LifecycleFn,
64 bootstrap_fn: LifecycleFn,
65 shutdown_fn: LifecycleFn,
66}
67
68impl ProviderDef {
69 pub fn of<T: Injectable>() -> Self {
71 Self {
72 type_id: TypeId::of::<T>(),
73 type_name: std::any::type_name::<T>(),
74 dependencies: T::dependencies(),
75 build: Box::new(|container| {
76 Box::pin(async move { Ok(Arc::new(T::create(container).await?) as ProviderValue) })
77 }),
78 init_fn: Box::new(|value| {
79 let value = downcast_provider::<T>(value);
80 Box::pin(async move { value?.on_module_init().await })
81 }),
82 bootstrap_fn: Box::new(|value| {
83 let value = downcast_provider::<T>(value);
84 Box::pin(async move { value?.on_bootstrap().await })
85 }),
86 shutdown_fn: Box::new(|value| {
87 let value = downcast_provider::<T>(value);
88 Box::pin(async move { value?.on_shutdown().await })
89 }),
90 }
91 }
92
93 pub fn instance<T: Send + Sync + 'static>(value: T) -> Self {
96 let value = Arc::new(value) as ProviderValue;
97 Self {
98 type_id: TypeId::of::<T>(),
99 type_name: std::any::type_name::<T>(),
100 dependencies: vec![],
101 build: Box::new(move |_| {
102 let value = value.clone();
103 Box::pin(async move { Ok(value) })
104 }),
105 init_fn: noop_lifecycle(),
106 bootstrap_fn: noop_lifecycle(),
107 shutdown_fn: noop_lifecycle(),
108 }
109 }
110
111 pub fn async_factory<T, Fut, E>(
113 dependencies: Vec<ProviderDependency>,
114 factory: impl Fn(Arc<Container>) -> Fut + Send + Sync + 'static,
115 ) -> Self
116 where
117 T: Send + Sync + 'static,
118 Fut: Future<Output = std::result::Result<T, E>> + Send + 'static,
119 E: Debug + Send + 'static,
120 {
121 Self {
122 type_id: TypeId::of::<T>(),
123 type_name: std::any::type_name::<T>(),
124 dependencies,
125 build: Box::new(move |container| {
126 let future = factory(Arc::new(container.clone()));
127 Box::pin(async move {
128 let value = future.await.map_err(|err| {
129 crate::exception::startup_error(format!(
130 "async factory failed for {}: {:?}",
131 std::any::type_name::<T>(),
132 err
133 ))
134 })?;
135 Ok(Arc::new(value) as ProviderValue)
136 })
137 }),
138 init_fn: noop_lifecycle(),
139 bootstrap_fn: noop_lifecycle(),
140 shutdown_fn: noop_lifecycle(),
141 }
142 }
143
144 pub fn type_id(&self) -> TypeId {
146 self.type_id
147 }
148 pub fn type_name(&self) -> &'static str {
150 self.type_name
151 }
152
153 fn assert_registered(&self, container: &Container) -> crate::Result<()> {
154 if container.contains_type_id(self.type_id) {
155 return Ok(());
156 }
157 Err(crate::exception::startup_error(format!(
158 "missing provider at startup: {} was declared by module metadata but was not registered",
159 self.type_name
160 )))
161 }
162
163 async fn run_lifecycle(
164 &self,
165 value: &ProviderValue,
166 hook: &'static str,
167 callback: &LifecycleFn,
168 ) -> crate::Result<()> {
169 callback(value).await.map_err(|err| {
170 crate::exception::startup_error(format!(
171 "{hook} failed for {}: {}: {}",
172 self.type_name, err.error, err.message
173 ))
174 })
175 }
176
177 async fn run_lifecycle_from_container(
178 &self,
179 container: &Container,
180 hook: &'static str,
181 callback: &LifecycleFn,
182 ) -> crate::Result<()> {
183 let value = container.resolve_erased(self.type_id).ok_or_else(|| crate::exception::startup_error(format!(
184 "missing provider during {hook}: {} was declared by module metadata but was not registered", self.type_name
185 )))?;
186 self.run_lifecycle(&value, hook, callback).await
187 }
188}
189
190pub struct ProviderOverrides {
192 defs: HashMap<TypeId, ProviderDef>,
193}
194impl ProviderOverrides {
195 pub fn new() -> Self {
197 Self {
198 defs: HashMap::new(),
199 }
200 }
201 pub fn insert_instance<T: Send + Sync + 'static>(mut self, value: T) -> Self {
203 self.defs
204 .insert(TypeId::of::<T>(), ProviderDef::instance(value));
205 self
206 }
207 pub fn insert_factory<T, Fut, E>(
209 mut self,
210 dependencies: Vec<ProviderDependency>,
211 factory: impl Fn(Arc<Container>) -> Fut + Send + Sync + 'static,
212 ) -> Self
213 where
214 T: Send + Sync + 'static,
215 Fut: Future<Output = std::result::Result<T, E>> + Send + 'static,
216 E: Debug + Send + 'static,
217 {
218 self.defs.insert(
219 TypeId::of::<T>(),
220 ProviderDef::async_factory::<T, Fut, E>(dependencies, factory),
221 );
222 self
223 }
224 pub fn insert(mut self, def: ProviderDef) -> Self {
226 self.defs.insert(def.type_id, def);
227 self
228 }
229 pub(crate) fn into_inner(self) -> HashMap<TypeId, ProviderDef> {
230 self.defs
231 }
232}
233impl Default for ProviderOverrides {
234 fn default() -> Self {
235 Self::new()
236 }
237}
238
239fn downcast_provider<T: Send + Sync + 'static>(value: &ProviderValue) -> crate::Result<Arc<T>> {
240 value.clone().downcast::<T>().map_err(|_| {
241 crate::exception::startup_error(format!(
242 "type mismatch running lifecycle hook for {}",
243 std::any::type_name::<T>()
244 ))
245 })
246}
247fn noop_lifecycle() -> LifecycleFn {
248 Box::new(|_| Box::pin(async { Ok(()) }))
249}
250
251pub struct ControllerDef {
253 pub register_fn: fn(&mut dyn Any),
255 pub route_log_fn: fn(),
257 #[cfg(feature = "openapi")]
258 pub(crate) openapi_routes_fn: fn() -> &'static [crate::openapi::OpenApiRouteDef],
259 provider: ProviderDef,
260}
261impl ControllerDef {
262 pub fn of<C: Controller + Injectable + 'static>() -> Self {
264 let mut provider = ProviderDef::of::<C>();
265 for dependency in C::route_dependencies() {
266 if !provider
267 .dependencies
268 .iter()
269 .any(|existing| existing.type_id == dependency.type_id)
270 {
271 provider.dependencies.push(dependency);
272 }
273 }
274 Self {
275 register_fn: |any| C::register_routes(any),
276 route_log_fn: || crate::log_controller_routes::<C>(),
277 #[cfg(feature = "openapi")]
278 openapi_routes_fn: || C::openapi_routes(),
279 provider,
280 }
281 }
282}
283
284pub struct GatewayDef {
286 pub path: &'static str,
288 pub type_id: TypeId,
290 provider: ProviderDef,
291 kind: GatewayKind,
292}
293enum GatewayKind {
294 WebSocket {
295 resolve_fn: fn(&Container) -> crate::Result<Arc<dyn WebSocketGateway>>,
296 },
297 SocketIo {
298 register_fn: fn(&Container, &dyn Any) -> Result<()>,
299 },
300}
301impl GatewayDef {
302 pub fn websocket<G: WebSocketGateway>(path: &'static str) -> Self {
304 Self {
305 path,
306 type_id: TypeId::of::<G>(),
307 provider: ProviderDef::of::<G>(),
308 kind: GatewayKind::WebSocket {
309 resolve_fn: |c| Ok(c.resolve::<G>()? as Arc<dyn WebSocketGateway>),
310 },
311 }
312 }
313 #[doc(hidden)]
314 pub fn socket_io<G: Injectable>(
315 path: &'static str,
316 register_fn: fn(&Container, &dyn Any) -> crate::Result<()>,
317 ) -> Self {
318 Self {
319 path,
320 type_id: TypeId::of::<G>(),
321 provider: ProviderDef::of::<G>(),
322 kind: GatewayKind::SocketIo { register_fn },
323 }
324 }
325 pub fn resolve(&self, container: &Container) -> Result<Arc<dyn WebSocketGateway>> {
327 match self.kind {
328 GatewayKind::WebSocket { resolve_fn } => resolve_fn(container),
329 GatewayKind::SocketIo { .. } => Err(crate::exception::startup_error(format!(
330 "Socket.IO gateway {} cannot be mounted by an RFC 6455 application",
331 self.path
332 ))),
333 }
334 }
335 #[doc(hidden)]
336 pub fn is_websocket(&self) -> bool {
337 matches!(self.kind, GatewayKind::WebSocket { .. })
338 }
339 #[doc(hidden)]
340 pub fn register_socket_io(&self, container: &Container, handle: &dyn Any) -> Result<()> {
341 match self.kind {
342 GatewayKind::WebSocket { .. } => Ok(()),
343 GatewayKind::SocketIo { register_fn } => register_fn(container, handle),
344 }
345 }
346}
347pub trait Gateway: Injectable {
349 #[doc(hidden)]
350 fn definition() -> GatewayDef;
351}
352
353pub struct ModuleDef {
355 type_id: TypeId,
356 type_name: &'static str,
357 metadata_fn: fn() -> ModuleMetadata,
358 pub(crate) route_log_fn: fn(),
359}
360impl ModuleDef {
361 pub fn of<M: Module + 'static>() -> Self {
363 Self {
364 type_id: TypeId::of::<M>(),
365 type_name: std::any::type_name::<M>(),
366 metadata_fn: M::register,
367 route_log_fn: || crate::log_module_routes::<M>(),
368 }
369 }
370}
371pub trait Module {
373 fn register() -> ModuleMetadata;
375}
376
377pub struct ModuleMetadata {
379 pub imports: Vec<ModuleDef>,
381 pub providers: Vec<ProviderDef>,
383 pub controllers: Vec<ControllerDef>,
385 pub event_handlers: Vec<EventHandlerDef>,
387 pub gateways: Vec<GatewayDef>,
389 pub microservices: Vec<MicroserviceDef>,
391 exports: Vec<ProviderDependency>,
392 global: bool,
393}
394impl ModuleMetadata {
395 pub fn new() -> Self {
397 Self {
398 imports: vec![],
399 providers: vec![],
400 controllers: vec![],
401 event_handlers: vec![],
402 gateways: vec![],
403 microservices: vec![],
404 exports: vec![],
405 global: false,
406 }
407 }
408 pub fn global() -> Self {
410 let mut metadata = Self::new();
411 metadata.global = true;
412 metadata
413 }
414 pub fn import<M: Module + 'static>(mut self) -> Self {
416 self.imports.push(ModuleDef::of::<M>());
417 self
418 }
419 pub fn provider<T: Injectable>(mut self) -> Self {
421 self.providers.push(ProviderDef::of::<T>());
422 self
423 }
424 pub fn provider_async_factory<T, Fut, E>(
426 mut self,
427 dependencies: Vec<ProviderDependency>,
428 factory: impl Fn(Arc<Container>) -> Fut + Send + Sync + 'static,
429 ) -> Self
430 where
431 T: Send + Sync + 'static,
432 Fut: Future<Output = std::result::Result<T, E>> + Send + 'static,
433 E: Debug + Send + 'static,
434 {
435 self.providers.push(ProviderDef::async_factory::<T, Fut, E>(
436 dependencies,
437 factory,
438 ));
439 self
440 }
441 pub fn controller<C: Controller + Injectable + 'static>(mut self) -> Self {
443 self.controllers.push(ControllerDef::of::<C>());
444 self
445 }
446 pub fn gateway<G: Gateway>(mut self) -> Self {
448 self.gateways.push(G::definition());
449 self
450 }
451 pub fn microservice<T: Microservice>(mut self) -> Self {
456 self.microservices.push(T::definition());
457 self
458 }
459 pub fn event_handler<H>(mut self) -> Self
461 where
462 H: RegisterableEventHandler + EventHandler<H::Event>,
463 {
464 self.event_handlers.push(EventHandlerDef::of::<H>());
465 self
466 }
467 pub fn event_handler_for<E, H>(mut self) -> Self
469 where
470 E: Clone + Send + Sync + 'static,
471 H: Injectable + EventHandler<E>,
472 {
473 self.event_handlers
474 .push(EventHandlerDef::for_event::<E, H>());
475 self
476 }
477 pub fn export<T: Send + Sync + 'static>(mut self) -> Self {
479 self.exports.push(ProviderDependency::of::<T>());
480 self
481 }
482}
483impl Default for ModuleMetadata {
484 fn default() -> Self {
485 Self::new()
486 }
487}
488
489struct ModuleNode {
490 type_id: TypeId,
491 type_name: &'static str,
492 metadata: ModuleMetadata,
493 imports: Vec<usize>,
494}
495struct ModuleGraph {
496 nodes: Vec<ModuleNode>,
497}
498#[derive(Clone, Copy)]
499enum ProviderSlot {
500 Provider(usize),
501 Controller(usize),
502 Gateway(usize),
503 Microservice(usize),
504}
505#[derive(Clone, Copy)]
506struct ProviderRegistration {
507 module: usize,
508 slot: ProviderSlot,
509}
510
511impl ModuleGraph {
512 fn discover<M: Module + 'static>() -> crate::Result<Self> {
513 Self::discover_from(ModuleDef::of::<M>())
514 }
515 fn discover_from(root: ModuleDef) -> crate::Result<Self> {
516 fn visit(
517 def: ModuleDef,
518 graph: &mut Vec<ModuleNode>,
519 states: &mut HashMap<TypeId, u8>,
520 path: &mut Vec<&'static str>,
521 ) -> crate::Result<usize> {
522 match states.get(&def.type_id).copied() {
523 Some(2) => {
524 return Ok(graph
525 .iter()
526 .position(|node| node.type_id == def.type_id)
527 .expect("discovered module missing"));
528 }
529 Some(1) => {
530 let mut cycle = path.clone();
531 cycle.push(def.type_name);
532 return Err(crate::exception::startup_error(format!(
533 "circular module import: {}",
534 cycle.join(" -> ")
535 )));
536 }
537 _ => {}
538 }
539 states.insert(def.type_id, 1);
540 path.push(def.type_name);
541 let metadata = (def.metadata_fn)();
542 let index = graph.len();
543 graph.push(ModuleNode {
544 type_id: def.type_id,
545 type_name: def.type_name,
546 metadata,
547 imports: vec![],
548 });
549 let imports = std::mem::take(&mut graph[index].metadata.imports);
550 for import in imports {
551 let child = visit(import, graph, states, path)?;
552 graph[index].imports.push(child);
553 }
554 path.pop();
555 states.insert(def.type_id, 2);
556 Ok(index)
557 }
558 let mut nodes = vec![];
559 let mut states = HashMap::new();
560 let root_index = visit(root, &mut nodes, &mut states, &mut vec![])?;
561 let mut ordered = Vec::new();
563 let mut seen = HashSet::new();
564 fn order(
565 index: usize,
566 nodes: &Vec<ModuleNode>,
567 seen: &mut HashSet<usize>,
568 ordered: &mut Vec<usize>,
569 ) {
570 if !seen.insert(index) {
571 return;
572 }
573 for &child in &nodes[index].imports {
574 order(child, nodes, seen, ordered);
575 }
576 ordered.push(index);
577 }
578 order(root_index, &nodes, &mut seen, &mut ordered);
579 let mut remap = HashMap::new();
580 for (new, old) in ordered.iter().enumerate() {
581 remap.insert(*old, new);
582 }
583 let mut slots: Vec<Option<ModuleNode>> = nodes.into_iter().map(Some).collect();
584 let mut result = Vec::with_capacity(slots.len());
585 for old in ordered {
586 let mut node = slots[old]
587 .take()
588 .expect("module graph ordering repeated a node");
589 node.imports = node.imports.into_iter().map(|i| remap[&i]).collect();
590 result.push(node);
591 }
592 let _ = remap[&root_index];
593 Ok(Self { nodes: result })
594 }
595
596 fn definitions(&self) -> Vec<ProviderRegistration> {
597 let mut values = vec![];
598 for (module, node) in self.nodes.iter().enumerate() {
599 values.extend(
600 (0..node.metadata.providers.len()).map(|slot| ProviderRegistration {
601 module,
602 slot: ProviderSlot::Provider(slot),
603 }),
604 );
605 values.extend(
606 (0..node.metadata.controllers.len()).map(|slot| ProviderRegistration {
607 module,
608 slot: ProviderSlot::Controller(slot),
609 }),
610 );
611 for slot in 0..node.metadata.gateways.len() {
612 values.push(ProviderRegistration {
613 module,
614 slot: ProviderSlot::Gateway(slot),
615 });
616 }
617 values.extend((0..node.metadata.microservices.len()).map(|slot| {
618 ProviderRegistration {
619 module,
620 slot: ProviderSlot::Microservice(slot),
621 }
622 }));
623 }
624 values
625 }
626 fn def(&self, registration: ProviderRegistration) -> &ProviderDef {
627 match registration.slot {
628 ProviderSlot::Provider(index) => {
629 &self.nodes[registration.module].metadata.providers[index]
630 }
631 ProviderSlot::Controller(index) => {
632 &self.nodes[registration.module].metadata.controllers[index].provider
633 }
634 ProviderSlot::Gateway(index) => {
635 &self.nodes[registration.module].metadata.gateways[index].provider
636 }
637 ProviderSlot::Microservice(index) => {
638 &self.nodes[registration.module].metadata.microservices[index].provider
639 }
640 }
641 }
642 fn local_types(&self, module: usize) -> HashSet<TypeId> {
643 self.definitions()
644 .into_iter()
645 .filter(|r| r.module == module)
646 .map(|r| self.def(r).type_id)
647 .collect()
648 }
649 fn preflight(&self, container: Option<&Container>) -> crate::Result<Vec<ProviderRegistration>> {
655 let definitions = self.definitions();
656 let mut by_type = HashMap::new();
657 for registration in &definitions {
658 let def = self.def(*registration);
659 if let Some(existing) = by_type.insert(def.type_id, *registration) {
660 if !container.is_some_and(|container| {
661 container.has_pending_override(def.type_id)
662 || container.was_overridden(def.type_id)
663 }) {
664 return Err(crate::exception::startup_error(format!(
665 "duplicate provider registration for {} in {} and {}",
666 def.type_name,
667 self.nodes[existing.module].type_name,
668 self.nodes[registration.module].type_name
669 )));
670 }
671 }
672 }
673 let locals: Vec<HashSet<TypeId>> =
674 (0..self.nodes.len()).map(|i| self.local_types(i)).collect();
675 let mut exports = vec![HashSet::new(); self.nodes.len()];
676 for index in 0..self.nodes.len() {
677 let node = &self.nodes[index];
678 for export in &node.metadata.exports {
679 let imported = node
680 .imports
681 .iter()
682 .any(|&child| exports[child].contains(&export.type_id));
683 if !locals[index].contains(&export.type_id) && !imported {
684 return Err(crate::exception::startup_error(format!(
685 "module {} cannot export {}: it is neither declared locally nor exported by a direct import",
686 node.type_name, export.type_name
687 )));
688 }
689 exports[index].insert(export.type_id);
690 }
691 }
692 let global_exports: HashSet<TypeId> = self
693 .nodes
694 .iter()
695 .enumerate()
696 .filter(|(_, node)| node.metadata.global)
697 .flat_map(|(index, _)| exports[index].iter().copied())
698 .collect();
699 let visible = |module: usize, type_id: TypeId| {
700 locals[module].contains(&type_id)
701 || global_exports.contains(&type_id)
702 || self.nodes[module]
703 .imports
704 .iter()
705 .any(|&child| exports[child].contains(&type_id))
706 };
707 for registration in &definitions {
708 let production = self.def(*registration);
709 let effective = container
710 .and_then(|container| container.pending_override(production.type_id))
711 .unwrap_or(production);
712 for dependency in &effective.dependencies {
713 if dependency.type_id == TypeId::of::<crate::Logger>() {
714 continue;
715 }
716 if by_type.contains_key(&dependency.type_id) {
717 if !visible(registration.module, dependency.type_id) {
718 return Err(crate::exception::startup_error(format!(
719 "{} depends on {} but it is not visible in module {}; import and export its module",
720 effective.type_name,
721 dependency.type_name,
722 self.nodes[registration.module].type_name
723 )));
724 }
725 } else if !container
726 .is_some_and(|container| container.contains_type_id(dependency.type_id))
727 {
728 return Err(crate::exception::startup_error(format!(
729 "missing provider at startup: {} depends on {} but no provider is registered",
730 effective.type_name, dependency.type_name
731 )));
732 }
733 }
734 }
735 for (module, node) in self.nodes.iter().enumerate() {
736 for handler in &node.metadata.event_handlers {
737 handler.assert_registered_or_declared(&locals[module])?;
738 if !visible(module, TypeId::of::<crate::EventBus>()) {
739 return Err(crate::exception::startup_error(format!(
740 "no provider registered for EventBus in module {}; import EventModule",
741 node.type_name
742 )));
743 }
744 }
745 }
746 let mut command_patterns: HashMap<&'static str, usize> = HashMap::new();
747 let mut event_patterns: HashMap<&'static str, usize> = HashMap::new();
748 for (module, node) in self.nodes.iter().enumerate() {
749 for microservice in &node.metadata.microservices {
750 for handler in microservice.handlers() {
751 if !valid_microservice_pattern(
752 handler.pattern,
753 handler.kind == MessageHandlerKind::Command,
754 ) {
755 return Err(crate::exception::startup_error(format!(
756 "invalid microservice subject `{}` in module {}",
757 handler.pattern, node.type_name
758 )));
759 }
760 let (other, existing) = if handler.kind == MessageHandlerKind::Command {
761 (&event_patterns, command_patterns.get(handler.pattern))
762 } else {
763 (&command_patterns, event_patterns.get(handler.pattern))
764 };
765 if let Some(other_module) = other.get(handler.pattern) {
766 return Err(crate::exception::startup_error(format!(
767 "command and event handlers cannot share subject `{}` in {} and {}",
768 handler.pattern, self.nodes[*other_module].type_name, node.type_name
769 )));
770 }
771 if let Some(existing) = existing {
772 return Err(crate::exception::startup_error(format!(
773 "duplicate {:?} handler subject `{}` in {} and {}",
774 handler.kind,
775 handler.pattern,
776 self.nodes[*existing].type_name,
777 node.type_name
778 )));
779 }
780 if handler.kind == MessageHandlerKind::Command {
781 command_patterns.insert(handler.pattern, module);
782 } else {
783 event_patterns.insert(handler.pattern, module);
784 }
785 }
786 }
787 }
788 for command in command_patterns.keys() {
789 for event in event_patterns.keys() {
790 if microservice_patterns_intersect(command, event) {
791 return Err(crate::exception::startup_error(format!(
792 "command subject `{command}` overlaps event subject `{event}`; command and event transports must be disjoint"
793 )));
794 }
795 }
796 }
797 let event_subjects: Vec<_> = event_patterns.keys().copied().collect();
798 for (index, first) in event_subjects.iter().enumerate() {
799 for second in event_subjects.iter().skip(index + 1) {
800 if microservice_patterns_intersect(first, second) {
801 return Err(crate::exception::startup_error(format!(
802 "event subjects `{first}` and `{second}` overlap; each event delivery must have one owner"
803 )));
804 }
805 }
806 }
807 let mut sorted = vec![];
808 let mut states = HashMap::new();
809 let mut stack = vec![];
810 fn schedule(
811 reg: ProviderRegistration,
812 graph: &ModuleGraph,
813 by_type: &HashMap<TypeId, ProviderRegistration>,
814 container: Option<&Container>,
815 states: &mut HashMap<TypeId, u8>,
816 stack: &mut Vec<&'static str>,
817 sorted: &mut Vec<ProviderRegistration>,
818 ) -> crate::Result<()> {
819 let def = graph.def(reg);
820 match states.get(&def.type_id).copied() {
821 Some(2) => return Ok(()),
822 Some(1) => {
823 let mut cycle = stack.clone();
824 cycle.push(def.type_name);
825 return Err(crate::exception::startup_error(format!(
826 "provider dependency cycle: {}",
827 cycle.join(" -> ")
828 )));
829 }
830 _ => {}
831 }
832 states.insert(def.type_id, 1);
833 stack.push(def.type_name);
834 let effective = container
835 .and_then(|container| container.pending_override(def.type_id))
836 .unwrap_or(def);
837 for dep in &effective.dependencies {
838 if let Some(next) = by_type.get(&dep.type_id) {
839 schedule(*next, graph, by_type, container, states, stack, sorted)?;
840 }
841 }
842 stack.pop();
843 states.insert(def.type_id, 2);
844 sorted.push(reg);
845 Ok(())
846 }
847 for registration in definitions {
848 schedule(
849 registration,
850 self,
851 &by_type,
852 container,
853 &mut states,
854 &mut stack,
855 &mut sorted,
856 )?;
857 }
858 Ok(sorted)
859 }
860 fn def_by_type(&self, type_id: TypeId) -> Option<&ProviderDef> {
861 self.definitions().into_iter().find_map(|r| {
862 let def = self.def(r);
863 (def.type_id == type_id).then_some(def)
864 })
865 }
866}
867
868async fn initialize_graph(graph: &ModuleGraph, container: &mut Container) -> crate::Result<()> {
869 let order = graph.preflight(Some(container))?;
870 for registration in order {
871 let declared = graph.def(registration);
872 container.mark_provider_declared(declared.type_id);
873 if container.contains_type_id(declared.type_id)
874 || container.was_overridden(declared.type_id)
875 {
876 continue;
877 }
878 let start = Instant::now();
879 let override_def = container.take_pending_override(declared.type_id);
880 if override_def.is_some() {
881 container.mark_override_applied(declared.type_id);
882 }
883 let effective = override_def.as_ref().unwrap_or(declared);
884 let scoped_container =
885 container.scoped_for_provider(effective.type_name, &effective.dependencies);
886 let value = match (effective.build)(&scoped_container).await {
887 Ok(value) => value,
888 Err(error) => {
889 rollback_graph(graph, container).await;
890 return Err(error);
891 }
892 };
893 container.register_erased(effective.type_id, value.clone());
894 if let Err(error) = effective
895 .run_lifecycle(&value, "on_module_init", &effective.init_fn)
896 .await
897 {
898 rollback_graph(graph, container).await;
899 return Err(error);
900 }
901 if override_def.is_none() {
902 container.record_initialized_provider(declared.type_id);
903 }
904 crate::log_provider_initialized(effective.type_name, start.elapsed());
905 }
906 for node in &graph.nodes {
907 for handler in &node.metadata.event_handlers {
908 if let Err(error) = handler.register(container) {
909 rollback_graph(graph, container).await;
910 return Err(error);
911 }
912 }
913 crate::log_module_initialized(node.type_name, std::time::Duration::ZERO);
914 }
915 Ok(())
916}
917
918async fn bootstrap_graph(graph: &ModuleGraph, container: &Container) -> crate::Result<()> {
919 let order = graph.preflight(Some(container))?;
920 let initialized: HashSet<TypeId> = container.initialized_provider_types().into_iter().collect();
921 for registration in order {
922 let def = graph.def(registration);
923 if initialized.contains(&def.type_id)
924 && !container.was_overridden(def.type_id)
925 && container.begin_provider_bootstrap(def.type_id)
926 {
927 if let Err(error) = def
928 .run_lifecycle_from_container(container, "on_bootstrap", &def.bootstrap_fn)
929 .await
930 {
931 rollback_graph(graph, container).await;
932 return Err(error);
933 }
934 }
935 }
936 Ok(())
937}
938
939async fn rollback_graph(graph: &ModuleGraph, container: &Container) {
940 for type_id in container.take_initialized_providers().into_iter().rev() {
941 if let Some(def) = graph.def_by_type(type_id) {
942 let _ = def
943 .run_lifecycle_from_container(container, "on_shutdown", &def.shutdown_fn)
944 .await;
945 }
946 }
947}
948
949pub async fn register_module<M: Module + 'static>(container: &mut Container) -> Result<()> {
951 let graph = ModuleGraph::discover::<M>()?;
952 initialize_graph(&graph, container).await
953}
954pub async fn bootstrap_module<M: Module + 'static>(container: &Container) -> Result<()> {
956 let graph = ModuleGraph::discover::<M>()?;
957 bootstrap_graph(&graph, container).await
958}
959pub async fn shutdown_module<M: Module + 'static>(container: &Container) -> Result<()> {
961 let graph = ModuleGraph::discover::<M>()?;
962 let mut first = None;
963 for type_id in container.take_initialized_providers().into_iter().rev() {
964 if let Some(def) = graph.def_by_type(type_id) {
965 if let Err(error) = def
966 .run_lifecycle_from_container(container, "on_shutdown", &def.shutdown_fn)
967 .await
968 {
969 if first.is_none() {
970 first = Some(error);
971 }
972 }
973 }
974 }
975 first.map_or(Ok(()), Err)
976}
977
978pub async fn build_container<M: Module + 'static>() -> Result<Container> {
980 build_container_with_overrides::<M>(ProviderOverrides::new()).await
981}
982#[doc(hidden)]
983pub async fn build_container_with_setup<M: Module + 'static>(
984 setup: impl FnOnce(&mut Container),
985) -> Result<Container> {
986 crate::log_application_starting();
987 let mut container = Container::new();
988 setup(&mut container);
989 if let Err(error) = register_module::<M>(&mut container).await {
990 return Err(error);
991 }
992 if let Err(error) =
993 validate_module_providers::<M>(&container).and_then(|_| validate_gateway_paths::<M>())
994 {
995 let graph = ModuleGraph::discover::<M>()?;
996 rollback_graph(&graph, &container).await;
997 return Err(error);
998 }
999 if let Err(error) = bootstrap_module::<M>(&container).await {
1000 return Err(error);
1001 }
1002 Ok(container)
1003}
1004pub async fn build_container_with_overrides<M: Module + 'static>(
1006 overrides: ProviderOverrides,
1007) -> crate::Result<Container> {
1008 crate::log_application_starting();
1009 let mut container = Container::new();
1010 container.seed_overrides(overrides);
1011 if let Err(error) = register_module::<M>(&mut container).await {
1012 return Err(error);
1013 }
1014 if let Err(error) = container
1015 .assert_no_unused_overrides()
1016 .and_then(|_| validate_module_providers::<M>(&container))
1017 .and_then(|_| validate_gateway_paths::<M>())
1018 {
1019 let graph = ModuleGraph::discover::<M>()?;
1020 rollback_graph(&graph, &container).await;
1021 return Err(error);
1022 }
1023 if let Err(error) = bootstrap_module::<M>(&container).await {
1024 return Err(error);
1025 }
1026 Ok(container)
1027}
1028
1029pub fn collect_module_message_handlers<M: Module + 'static>() -> Result<Vec<MessageHandlerDef>> {
1035 collect_module_message_handlers_with_container::<M>(None)
1036}
1037
1038pub fn collect_module_message_handlers_with_container<M: Module + 'static>(
1042 container: Option<&Container>,
1043) -> Result<Vec<MessageHandlerDef>> {
1044 let graph = ModuleGraph::discover::<M>()?;
1045 graph.preflight(container)?;
1046 let mut handlers = Vec::new();
1047 for node in &graph.nodes {
1048 for microservice in &node.metadata.microservices {
1049 handlers.extend(microservice.handlers());
1050 }
1051 }
1052 Ok(handlers)
1053}
1054
1055fn validate_gateway_paths_in_graph(graph: &ModuleGraph) -> crate::Result<()> {
1056 let mut paths = HashSet::new();
1057 for node in &graph.nodes {
1058 for gateway in &node.metadata.gateways {
1059 if !gateway.path.starts_with('/') {
1060 return Err(crate::exception::startup_error(format!(
1061 "websocket gateway path must start with '/': {}",
1062 gateway.path
1063 )));
1064 }
1065 if !paths.insert((gateway.path, gateway.is_websocket())) {
1066 return Err(crate::exception::startup_error(format!(
1067 "duplicate gateway path: {}",
1068 gateway.path
1069 )));
1070 }
1071 }
1072 }
1073 Ok(())
1074}
1075
1076fn valid_microservice_pattern(pattern: &str, command: bool) -> bool {
1077 if pattern.is_empty() || pattern.chars().any(char::is_whitespace) {
1078 return false;
1079 }
1080 let tokens: Vec<_> = pattern.split('.').collect();
1081 tokens.iter().enumerate().all(|(index, token)| {
1082 !token.is_empty()
1083 && (!token.contains('*') || (!command && *token == "*"))
1084 && (!token.contains('>') || (!command && *token == ">" && index + 1 == tokens.len()))
1085 })
1086}
1087
1088fn microservice_patterns_intersect(first: &str, second: &str) -> bool {
1089 let first: Vec<_> = first.split('.').collect();
1090 let second: Vec<_> = second.split('.').collect();
1091 let mut index = 0;
1092 loop {
1093 let left = first.get(index).copied();
1094 let right = second.get(index).copied();
1095 match (left, right) {
1096 (None, None) => return true,
1097 (Some(">"), Some(_)) | (Some(_), Some(">")) => return true,
1098 (Some(left), Some(right)) if left == "*" || right == "*" || left == right => {
1099 index += 1;
1100 }
1101 _ => return false,
1102 }
1103 }
1104}
1105
1106#[cfg(test)]
1107mod microservice_pattern_tests {
1108 use super::microservice_patterns_intersect;
1109
1110 #[test]
1111 fn terminal_wildcards_do_not_overlap_their_empty_prefix() {
1112 assert!(!microservice_patterns_intersect("orders", "orders.>"));
1113 assert!(microservice_patterns_intersect(
1114 "orders.created",
1115 "orders.>"
1116 ));
1117 }
1118}
1119
1120fn validate_gateway_paths<M: Module + 'static>() -> crate::Result<()> {
1121 validate_gateway_paths_in_graph(&ModuleGraph::discover::<M>()?)
1122}
1123
1124pub fn validate_module<M: Module + 'static>() -> Result<()> {
1131 let graph = ModuleGraph::discover::<M>()?;
1132 graph.preflight(None)?;
1133 validate_gateway_paths_in_graph(&graph)
1134}
1135
1136pub fn validate_module_providers<M: Module + 'static>(container: &Container) -> Result<()> {
1138 let graph = ModuleGraph::discover::<M>()?;
1139 graph.preflight(Some(container))?;
1140 for registration in graph.definitions() {
1141 graph.def(registration).assert_registered(container)?;
1142 }
1143 Ok(())
1144}
1145
1146pub fn register_module_controllers<M: Module + 'static>(any: &mut dyn Any) {
1148 if let Ok(graph) = ModuleGraph::discover::<M>() {
1149 for node in graph.nodes {
1150 for controller in &node.metadata.controllers {
1151 (controller.register_fn)(any);
1152 }
1153 }
1154 }
1155}
1156#[cfg(feature = "openapi")]
1157#[doc(hidden)]
1158pub fn visit_module_openapi_routes<M: Module + 'static>(
1159 visitor: &mut impl FnMut(&crate::openapi::OpenApiRouteDef),
1160) {
1161 if let Ok(graph) = ModuleGraph::discover::<M>() {
1162 for node in graph.nodes {
1163 for controller in &node.metadata.controllers {
1164 for route in (controller.openapi_routes_fn)() {
1165 visitor(route);
1166 }
1167 }
1168 }
1169 }
1170}
1171pub fn visit_module_gateways<M: Module + 'static>(visitor: &mut impl FnMut(&GatewayDef)) {
1173 if let Ok(graph) = ModuleGraph::discover::<M>() {
1174 let mut seen = HashSet::new();
1175 for node in graph.nodes {
1176 for gateway in &node.metadata.gateways {
1177 if seen.insert(gateway.type_id) {
1178 visitor(gateway);
1179 }
1180 }
1181 }
1182 }
1183}