lexe_common/constants/timeout.rs
1//! Timeout constants, organized into nested modules named after the API trait,
2//! service, or struct whose timeouts it holds.
3//!
4//! `const_assert!`s are used to enforce our timeout hierarchies; e.g. each
5//! timeout along a request chain must be shorter than the one enclosing it.
6//!
7//! Principles for tuning:
8//!
9//! - When a timeout increase is needed: prefer to raise the timeout for a
10//! specific server or client method that needs it, rather than the global
11//! default.
12//! - Be careful when decreasing timeouts baked into enclave programs - if it
13//! cannot be overridden via CLI, there is no way to backtrack if the decrease
14//! was too aggressive. Wire through a CLI arg before decreasing the timeout.
15
16use std::time::Duration;
17
18use lexe_std::const_assert;
19
20/// The minimum tolerance every service should have for transient errors caused
21/// by restarts of this service's dependencies.
22///
23/// Notably, channel manager and channel monitor persists will try for up to
24/// this long before initiating a node shutdown.
25pub const TRANSIENT_ERROR_TOLERANCE: Duration = Duration::from_secs(30);
26
27/// Defaults for Lexe API servers.
28pub mod server {
29 use super::*;
30
31 /// The grace period passed to `axum_server::Handle::graceful_shutdown`
32 /// during which new connections are refused and we wait for existing
33 /// connections to terminate before initiating a hard shutdown.
34 pub const SHUTDOWN_GRACE_PERIOD: Duration = Duration::from_secs(3);
35
36 /// The maximum time we'll wait for a server to complete shutdown.
37 pub const SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);
38
39 /// The default maximum time a server can spend handling a request.
40 pub const DEFAULT_HANDLER_TIMEOUT: Duration = Duration::from_secs(25);
41
42 const_assert!(SHUTDOWN_TIMEOUT.as_secs() > SHUTDOWN_GRACE_PERIOD.as_secs());
43}
44
45/// Defaults for Lexe `RestClient`s.
46pub mod client {
47 use super::*;
48
49 /// The default request timeout for Lexe `RestClient`s.
50 pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(30);
51
52 const_assert!(
53 DEFAULT_TIMEOUT.as_secs() > server::DEFAULT_HANDLER_TIMEOUT.as_secs()
54 );
55}
56
57/// Timeouts for `UserNode`s.
58pub mod usernode {
59 use super::*;
60
61 /// Default sync timeout for user nodes (BDK/LDK sync).
62 //
63 // (2026-07-24): 30s -> 15s. The const was created at 30s despite 15s being
64 // the documented default; prod doesn't override it.
65 pub const DEFAULT_SYNC_TIMEOUT: Duration = Duration::from_secs(15);
66
67 /// The amount of time user node tasks have to finish after a graceful
68 /// shutdown signal is received before the task is forced to exit.
69 pub const SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(35);
70
71 // The meganode's `run_user` handler (bounded by the default
72 // `server::DEFAULT_HANDLER_TIMEOUT`) blocks on the usernode's boot sync
73 // before responding.
74 const_assert!(
75 DEFAULT_SYNC_TIMEOUT.as_secs()
76 < server::DEFAULT_HANDLER_TIMEOUT.as_secs()
77 );
78 const_assert!(
79 SHUTDOWN_TIMEOUT.as_secs() > server::SHUTDOWN_TIMEOUT.as_secs()
80 );
81 // A shutting-down node must still afford a full critical-persist attempt.
82 const_assert!(
83 TRANSIENT_ERROR_TOLERANCE.as_secs() < SHUTDOWN_TIMEOUT.as_secs()
84 );
85}
86
87/// Timeouts for in-enclave `UserRunner`.
88pub mod userrunner {
89 use super::*;
90
91 /// The amount of time the user runner has to finish after a graceful
92 /// shutdown signal is received before the program is forced to exit.
93 pub const SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(37);
94
95 const_assert!(
96 SHUTDOWN_TIMEOUT.as_secs() > usernode::SHUTDOWN_TIMEOUT.as_secs()
97 );
98}
99
100/// Lifetimes and renewal policy for leases.
101///
102/// A lease holder must be fully shut down before its lease expires. Renewal
103/// failure is detected at latest `interval + RENEW_ROUND_BUDGET` after the
104/// last successful renewal, so each holder `const_assert!`s that this
105/// detection latency plus its drain time fits within its lease lifetime.
106pub mod lease {
107 use super::*;
108
109 /// The total time budget for a lease renewal round.
110 pub const RENEW_ROUND_BUDGET: Duration = Duration::from_secs(10);
111
112 /// The timeout for a single lease request: an acquire, a release, or
113 /// one renewal attempt.
114 pub const REQUEST_TIMEOUT: Duration = Duration::from_secs(3);
115}
116
117/// Timeouts for `UserNodeProvisionApi` (User -> Node).
118pub mod user_node_provision_api {
119 use super::*;
120
121 /// `NodeClient`'s request timeout for provisioning. Generous because the
122 /// provision handler does the Google Drive OAuth exchange and GVFS setup.
123 pub const CLIENT_TIMEOUT: Duration = Duration::from_secs(30);
124
125 const_assert!(
126 CLIENT_TIMEOUT.as_secs() > server::DEFAULT_HANDLER_TIMEOUT.as_secs()
127 );
128}
129
130/// Timeouts for `UserNodeRunApi` (User -> Node).
131pub mod user_node_run_api {
132 use super::*;
133
134 /// Handling timeout for the node's user-facing server. Generous because
135 /// `[preflight_]pay_invoice` may compute `max_flow`, which takes ~30s at
136 /// 10 iterations and ~50s at 17 iterations.
137 /// See `compute_max_flow_to_recipient` for more details.
138 pub const SERVER_HANDLER_TIMEOUT: Duration = Duration::from_secs(60);
139
140 /// Timeouts for endpoints which may compute `max_flow`.
141 pub mod max_flow {
142 use super::*;
143
144 /// Client timeout for endpoints which may compute `max_flow`.
145 pub const CLIENT_TIMEOUT: Duration = Duration::from_secs(62);
146
147 const_assert!(
148 CLIENT_TIMEOUT.as_secs()
149 > user_node_run_api::SERVER_HANDLER_TIMEOUT.as_secs()
150 );
151 }
152}