appcore_api/http/
state.rs1use crate::ApiRouter;
14use appcore_core::{RuntimeController, RuntimeOperationalMode};
15use parking_lot::Mutex;
16use std::sync::atomic::AtomicU64;
17use std::sync::Arc;
18
19use super::auth::HttpCommandAuth;
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct HttpApiConfig {
24 pub host: String,
26 pub port: u16,
28 pub enabled: bool,
30 pub max_payload_bytes: usize,
32}
33
34impl Default for HttpApiConfig {
35 fn default() -> Self {
36 Self {
37 host: "127.0.0.1".to_string(),
38 port: 8080,
39 enabled: false,
40 max_payload_bytes: 65_536,
41 }
42 }
43}
44
45#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
46pub struct RuntimeStaticInfo {
48 pub app_id: String,
50 pub node_id: String,
52 pub tenant_id: String,
54 pub cluster_id: String,
56 pub core_id: String,
58 pub operation_mode: String,
60 pub storage_status: String,
62 pub security_ok: bool,
64 pub api_enabled: bool,
66 pub sync_enabled: bool,
68 pub sync_role: String,
70 pub sync_log_len: usize,
72 pub sync_log_path: Option<String>,
74 pub sync_checkpoint_path: Option<String>,
76 pub sync_peers: Vec<String>,
78 pub sync_dns_enabled: bool,
80 pub sync_dns_seeds: Vec<String>,
82 pub sync_dns_default_port: u16,
84 pub idempotency_ttl_ms: u64,
86 pub idempotency_path: Option<String>,
88}
89
90#[derive(Clone)]
91pub(crate) struct HttpState {
92 pub(crate) static_info: RuntimeStaticInfo,
93 pub(crate) controller: Option<Arc<Mutex<RuntimeController>>>,
94 pub(crate) app_query_router: Option<Arc<Mutex<ApiRouter>>>,
95 pub(crate) sync_log: Option<Arc<dyn SyncLogView>>,
96 pub(crate) tick_counter: Option<Arc<AtomicU64>>,
97 pub(crate) operation_mode: Option<Arc<Mutex<RuntimeOperationalMode>>>,
98 pub(crate) command_policy: Option<Arc<dyn CommandCapabilityPolicy>>,
99 pub(crate) supervisor: Option<appcore_supervisor::Supervisor>,
100 pub(crate) auth: HttpCommandAuth,
101 pub(crate) max_payload_bytes: usize,
102 pub(crate) clock: Arc<dyn appcore_core::Clock>,
103}
104
105#[derive(Debug, Clone, PartialEq, Eq)]
106pub enum CommandCapabilityPolicyError {
108 CapabilityNotDeclared,
110 MissingIdempotencyKey,
112 RequiresLeader,
114 LeaseExpired,
116 StaleEpoch,
118 ReadOnly,
120 Rejected(String),
122}
123
124pub trait CommandCapabilityPolicy: Send + Sync {
126 fn authorize_command(
128 &self,
129 command_name: &str,
130 idempotency_key: Option<&str>,
131 now_ms: u64,
132 ) -> Result<(), CommandCapabilityPolicyError>;
133
134 fn authorize_query(
136 &self,
137 _query_name: &str,
138 _now_ms: u64,
139 ) -> Result<(), CommandCapabilityPolicyError> {
140 Ok(())
141 }
142}
143
144pub trait SyncLogView: Send + Sync {
146 fn len(&self) -> Result<usize, SyncLogViewError>;
148
149 fn is_empty(&self) -> Result<bool, SyncLogViewError> {
151 self.len().map(|length| length == 0)
152 }
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq)]
157pub struct SyncLogViewError;
158
159impl std::fmt::Display for SyncLogViewError {
160 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 formatter.write_str("synchronization log observation failed")
162 }
163}
164
165impl std::error::Error for SyncLogViewError {}