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
use crateAppContext;
use crate;
use async_trait;
use FromRef;
/// Trait used to hook into various stages of the app's lifecycle.
///
/// This trait has some overlap with the [`crate::health::check::HealthCheck`]. For example, both
/// traits have methods that are called during app startup before the app's services are started.
/// However, health checks are intended to be used both during app startup and in the
/// `/api/_health` API endpoint. This enforces a constraint on the
/// [`crate::health::check::HealthCheck`] trait that doesn't exist for the [`AppLifecycleHandler`]
/// trait -- the [`crate::health::check::HealthCheck`] is stored in the
/// [`crate::app::context::AppContext`], which means it can't take the state as a type parameter and
/// therefore also can't take it as parameter to its methods. Because this constraint only exists
/// for the health check use case, we split out the other lifecycle hooks into a separate trait that
/// allows better ergonomics -- instead of needing to store a weak reference to the app context as
/// in a health check, [`AppLifecycleHandler`] can simply accept the context as a parameter on its
/// methods.
///
/// The app's lifecycle generally looks something like this:
/// 1. Parse the [`crate::config::AppConfig`]
/// 2. Initialize tracing to enable logs/traces
/// 3. Build the [`crate::app::context::AppContext`] and the [`crate::app::App`]'s custom state
/// 4. Run the roadster/app CLI command, if one was specified when the app was started
/// 5. Register [`AppLifecycleHandler`]s, [`crate::health::check::HealthCheck`]s, and
/// [`crate::service::Service`]s
/// 6. Run the app's registered [`AppLifecycleHandler::before_health_checks`] hooks.
/// 7. Run the registered [`crate::health::check::HealthCheck`]s
/// 8. Run the app's registered [`AppLifecycleHandler::before_services`] hooks.
/// 9. Run the registered [`crate::service::Service`]s
/// 10. Wait for a shutdown signal, e.g., `Ctrl+c` or a custom signal from
/// [`crate::app::App::graceful_shutdown_signal`], and stop the [`crate::service::Service`]s
/// when the signal is received.
/// 11. Run Roadster's graceful shutdown logic
/// 12. Run the app's registered [`AppLifecycleHandler::on_shutdown`] hooks.