1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//! `Service` trait and `Inject<T>` extractor.
//!
//! A **service** is cheap composition from application resources. It is
//! constructed per request from application state `S` via [`Resolve<S>`],
//! NOT stored as a singleton, NOT resolved through a runtime container.
//!
//! The `#[service]` proc-macro generates:
//! - `impl DxComponent` -- the static name the module graph lists it under.
//! - `impl Service` -- the service marker + `DEPS` metadata.
//! - `impl Resolve<S>` -- per-state construction from field types.
//!
//! Handlers receive a service via the [`Inject<T>`] extractor, which is a
//! genuine Axum `FromRequestParts` implementation -- Axum remains the
//! handler runtime (no Arcature dispatcher).
//!
//! # Service dependency cycles
//!
//! Services compose by **value**, not by reference. A service `A` that
//! depends on service `B` stores `B` as a field. A cycle (`A` contains `B`
//! contains `A`) would require infinite size -- `rustc` rejects it at
//! compile time. No runtime cycle detection is needed; the type system
//! makes service cycles impossible.
//!
//! # Module service privacy
//!
//! A module's internal services are private by default. Privacy is
//! enforced by `rustc` visibility (a `pub(crate)` service cannot be named
//! outside its crate) and by `arc build` validation, which reports a module
//! that exports a name it does not declare as a service, a controller, or a
//! policy. An import naming a module that does not exist is rejected
//! earlier still, when the `ApplicationGraph` is constructed.
use FromRequestParts;
use Resolve;
use crateDxComponent;
/// A service: cheap per-request composition from application resources.
///
/// The `#[service]` macro generates this impl. The trait extends
/// [`DxComponent`] (for the static `NAME`) and adds `DEPS` -- the
/// dependency type names, read off the struct's fields.
///
/// `DEPS` lists the simple type names of the service's fields. For
/// `LinkService { db: Db, cache: Cache }`, `DEPS = ["Db", "Cache"]`.
/// Resources (Db, Cache) are leaf nodes in the graph; service-to-service
/// edges are the only ones that could cycle, and cannot: a service is
/// composed by value from its fields, so a cycle would not compile.
/// Axum extractor: construct a `T: Resolve<S>` from application state.
///
/// A genuine `FromRequestParts` implementation -- Axum remains the
/// handler runtime. The extractor calls `T::resolve(state)` to construct
/// the value cheaply from the application's `Arc`/`Clone`-backed
/// resources.
///
/// # Example
///
/// ```ignore
/// async fn show(link: Bound<Link>, svc: Inject<LinkService>) -> Result<Json<Link>> {
/// let link = link.into_inner();
/// let report = svc.recent_for(link.id);
/// // ...
/// }
/// ```
///
/// `Inject<T>` works for any `T: Resolve<S>`, including built-in resources
/// (`Inject<Db>`) and services (`Inject<LinkService>`). The `Service`
/// trait is metadata, not a bound on the extractor.
;