webx_core/
dispatch_runtime.rs1use std::sync::Arc;
19
20use crate::route::scan::HandlerCache;
21
22#[derive(Clone)]
27pub struct DispatchRuntime {
28 provider: Arc<rust_dix::ServiceProvider>,
29 handler_cache: Arc<HandlerCache>,
30}
31
32impl DispatchRuntime {
33 pub fn new(provider: Arc<rust_dix::ServiceProvider>, handler_cache: Arc<HandlerCache>) -> Self {
34 Self {
35 provider,
36 handler_cache,
37 }
38 }
39
40 pub fn provider(&self) -> &Arc<rust_dix::ServiceProvider> {
42 &self.provider
43 }
44
45 pub fn handler_cache(&self) -> &Arc<HandlerCache> {
47 &self.handler_cache
48 }
49
50 pub fn scope(&self) -> rust_dix::Scope {
55 self.provider.scope()
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use rust_dix::ServiceCollection;
63 use std::sync::atomic::{AtomicUsize, Ordering};
64
65 #[derive(Debug)]
66 struct ScopedThing(usize);
67
68 fn runtime_with_scoped_counter() -> (Arc<DispatchRuntime>, Arc<AtomicUsize>) {
69 let created = Arc::new(AtomicUsize::new(0));
70 let counter = Arc::clone(&created);
71 let provider = ServiceCollection::new()
72 .scoped::<ScopedThing>(move |_| {
73 let n = counter.fetch_add(1, Ordering::SeqCst);
74 Arc::new(ScopedThing(n))
75 })
76 .build()
77 .expect("provider");
78 (
79 Arc::new(DispatchRuntime::new(
80 provider,
81 Arc::new(HandlerCache::build()),
82 )),
83 created,
84 )
85 }
86
87 #[tokio::test]
90 async fn runtime_scope_is_the_explicit_di_entry_point() {
91 let (runtime, created) = runtime_with_scoped_counter();
92
93 let scope = runtime.scope();
94 let first = scope.get::<ScopedThing>().expect("scoped in scope");
95 let second = scope.get::<ScopedThing>().expect("scoped in scope");
96 assert!(
97 Arc::ptr_eq(&first, &second),
98 "Scoped services are cached per scope"
99 );
100 assert_eq!(first.0, 0, "the scope created the service once");
101 assert_eq!(created.load(Ordering::SeqCst), 1);
102
103 let error = runtime
104 .provider()
105 .get::<ScopedThing>()
106 .expect_err("strict scope validation rejects Scoped services from the root");
107 assert!(error.to_string().contains("root provider"), "{error}");
108 }
109}