use crate::scripting::engine::{LuaPool, ScriptCache, ScriptIndex};
use crate::scripting::ScriptStats;
use crate::server::cursor_store::CursorStore;
use crate::server::service_cache::ServiceCache;
use crate::server::upload_session::UploadSessionStore;
use crate::storage::StorageEngine;
use axum::response::Json;
use serde_json::Value;
use std::sync::Arc;
pub const PROTECTED_COLLECTIONS: [&str; 2] = ["_admins", "_api_keys"];
#[inline]
pub fn is_protected_collection(db_name: &str, coll_name: &str) -> bool {
db_name == "_system" && PROTECTED_COLLECTIONS.contains(&coll_name)
}
#[inline]
pub fn is_physical_shard_collection(name: &str) -> bool {
if let Some(pos) = name.rfind("_s") {
let suffix = &name[pos + 2..];
!suffix.is_empty() && suffix.chars().all(|c| c.is_ascii_digit())
} else {
false
}
}
pub fn sanitize_filename(filename: &str) -> String {
filename
.chars()
.filter(|c| c.is_ascii() && *c != '"' && *c != '\\' && *c != '\n' && *c != '\r')
.collect::<String>()
.trim()
.to_string()
}
pub fn get_dir_size(path: impl AsRef<std::path::Path>) -> std::io::Result<u64> {
let mut size = 0;
if path.as_ref().is_dir() {
for entry in std::fs::read_dir(path)? {
let entry = entry?;
let metadata = entry.metadata()?;
if metadata.is_dir() {
size += get_dir_size(entry.path())?;
} else {
size += metadata.len();
}
}
} else {
size = std::fs::metadata(path)?.len();
}
Ok(size)
}
#[derive(Clone)]
pub struct AppState {
pub storage: Arc<StorageEngine>,
pub cursor_store: CursorStore,
pub cluster_manager: Option<Arc<crate::cluster::manager::ClusterManager>>,
pub replication_log: Option<Arc<crate::sync::log::SyncLog>>,
pub shard_coordinator: Option<Arc<crate::sharding::ShardCoordinator>>,
pub startup_time: std::time::Instant,
pub request_counter: Arc<std::sync::atomic::AtomicU64>,
pub query_counter: Arc<std::sync::atomic::AtomicU64>,
pub write_counter: Arc<std::sync::atomic::AtomicU64>,
pub system_monitor: Arc<std::sync::Mutex<sysinfo::System>>,
pub queue_worker: Option<Arc<crate::queue::QueueWorker>>,
pub script_stats: Arc<ScriptStats>,
pub stream_manager: Option<Arc<crate::stream::StreamManager>>,
pub permission_cache: crate::server::permission_cache::PermissionCache,
pub repl_sessions: crate::server::repl_session::ReplSessionStore,
pub channel_manager: Arc<crate::scripting::ChannelManager>,
pub sync_session_manager: Option<Arc<crate::sync::SyncSessionManager>>,
pub lua_pool: Option<Arc<LuaPool>>,
pub script_cache: Arc<ScriptCache>,
pub script_index: Arc<ScriptIndex>,
pub service_cache: Arc<ServiceCache>,
pub blob_rebalance_worker: Option<Arc<crate::sharding::BlobRebalanceWorker>>,
pub upload_session_store: UploadSessionStore,
}
impl AppState {
pub fn cluster_secret(&self) -> String {
self.storage
.cluster_config()
.and_then(|c| c.keyfile.clone())
.unwrap_or_default()
}
}
pub async fn health_check_handler() -> Json<Value> {
Json(serde_json::json!({
"status": "ok",
"timestamp": chrono::Utc::now().to_rfc3339()
}))
}