1use crate::config::GatewayConfig;
14use crate::metrics::GatewayMetrics;
15use crate::tenant::TenantState;
16use crate::GatewayResult;
17use appcore_peer_rpc::{BoundedReplayStore, PeerNonceStore, ReplayStoreConfig};
18use appcore_security::HashTokenProvider;
19use appcore_types::TenantId;
20use parking_lot::RwLock;
21use std::collections::HashMap;
22use std::sync::Arc;
23use tokio::sync::watch;
24
25pub struct GatewayState {
27 config: GatewayConfig,
29
30 pub tenants: RwLock<HashMap<TenantId, TenantState>>,
32
33 pub metrics: Arc<GatewayMetrics>,
35
36 pub token_provider: HashTokenProvider,
38
39 connection_replay: Arc<dyn PeerNonceStore>,
40 shutdown: watch::Sender<bool>,
41}
42
43impl GatewayState {
44 pub fn new(config: GatewayConfig, token_provider: HashTokenProvider) -> GatewayResult<Self> {
46 Self::with_replay_store(
47 config,
48 token_provider,
49 Arc::new(BoundedReplayStore::new(ReplayStoreConfig::default())),
50 )
51 }
52
53 pub fn with_replay_store(
56 config: GatewayConfig,
57 token_provider: HashTokenProvider,
58 connection_replay: Arc<dyn PeerNonceStore>,
59 ) -> GatewayResult<Self> {
60 config.validate()?;
61 let (shutdown, _) = watch::channel(false);
62 Ok(Self {
63 config,
64 tenants: RwLock::new(HashMap::new()),
65 metrics: GatewayMetrics::new(),
66 token_provider,
67 connection_replay,
68 shutdown,
69 })
70 }
71
72 pub fn config(&self) -> &GatewayConfig {
74 &self.config
75 }
76
77 pub fn request_shutdown(&self) {
80 self.shutdown.send_replace(true);
81 }
82
83 pub fn is_shutting_down(&self) -> bool {
85 *self.shutdown.borrow()
86 }
87
88 pub(crate) fn subscribe_shutdown(&self) -> watch::Receiver<bool> {
89 self.shutdown.subscribe()
90 }
91
92 pub(crate) fn connection_replay(&self) -> &dyn PeerNonceStore {
93 self.connection_replay.as_ref()
94 }
95
96 pub(crate) async fn wait_for_shutdown(&self) {
97 let mut shutdown = self.subscribe_shutdown();
98 while !*shutdown.borrow() {
99 if shutdown.changed().await.is_err() {
100 break;
101 }
102 }
103 }
104}