refactor: 拆分 gateway 单体为独立 crate,新增 systemd 部署方案

将 gateway 内部的 model-fetch、provider-transport、scheduler-core、
usage-runtime、video-tasks-core 模块提取为独立 crate;重构 gateway
内部模块结构(state/router/cache/data/query 等);移除大量遗留模块
文件;新增 systemd 二进制部署骨架及相关文档;更新前端 usage 相关
API 和组件。
This commit is contained in:
fawney19
2026-04-05 20:23:16 +08:00
parent cbc811f6ce
commit 763ff03a7b
777 changed files with 42659 additions and 21469 deletions

View File

@@ -9,8 +9,11 @@ description = "Shared runtime/bootstrap helpers for Aether Rust services"
[dependencies]
async-stream.workspace = true
axum = { version = "0.8" }
chrono.workspace = true
futures-util.workspace = true
redis.workspace = true
serde_json.workspace = true
sha2.workspace = true
thiserror.workspace = true
tokio.workspace = true
tracing.workspace = true

View File

@@ -2,7 +2,7 @@ use crate::config::ServiceRuntimeConfig;
use crate::error::RuntimeBootstrapError;
pub fn init_service_runtime(config: ServiceRuntimeConfig) -> Result<(), RuntimeBootstrapError> {
crate::tracing::init_tracing(config)?;
crate::tracing::init_tracing(config.clone())?;
crate::metrics::init_metrics(config);
Ok(())
}

View File

@@ -1,6 +1,6 @@
use crate::observability::ServiceObservabilityConfig;
use crate::observability::{FileLoggingConfig, LogDestination, ServiceObservabilityConfig};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ServiceRuntimeConfig {
pub service_name: &'static str,
pub default_log_filter: &'static str,
@@ -21,6 +21,26 @@ impl ServiceRuntimeConfig {
self
}
pub const fn with_log_destination(mut self, log_destination: LogDestination) -> Self {
self.observability.log_destination = log_destination;
self
}
pub fn with_file_logging(mut self, file_logging: FileLoggingConfig) -> Self {
self.observability.file_logging = Some(file_logging);
self
}
pub fn with_node_role(mut self, node_role: impl Into<String>) -> Self {
self.observability.node_role = Some(node_role.into());
self
}
pub fn with_instance_id(mut self, instance_id: impl Into<String>) -> Self {
self.observability.instance_id = Some(instance_id.into());
self
}
pub const fn with_metrics_namespace(mut self, metrics_namespace: &'static str) -> Self {
self.observability.metrics_namespace = metrics_namespace;
self

View File

@@ -7,6 +7,7 @@ mod error;
pub mod metrics;
mod observability;
pub mod queue;
pub mod redaction;
pub mod shutdown;
pub mod task;
mod tracing;
@@ -23,9 +24,14 @@ pub use distributed::{
};
pub use error::RuntimeBootstrapError;
pub use metrics::{prometheus_response, service_up_sample, MetricKind, MetricLabel, MetricSample};
pub use observability::ServiceObservabilityConfig;
pub use observability::{
FileLoggingConfig, LogDestination, LogRotation, ServiceObservabilityConfig,
};
pub use queue::{
bounded_queue, BoundedQueueReceiver, BoundedQueueSender, QueueSendError, QueueSnapshot,
};
pub use redaction::{summarize_text_payload, TextPayloadSummary};
pub use shutdown::wait_for_shutdown_signal;
pub use tracing::{init_reloadable_tracing, LogFormat, LogReloader};
pub use tracing::{
init_reloadable_service_tracing, init_reloadable_tracing, LogFormat, LogReloader,
};

View File

@@ -1,9 +1,57 @@
use crate::tracing::LogFormat;
use std::path::PathBuf;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LogDestination {
Stdout,
File,
Both,
}
impl LogDestination {
pub const fn needs_file_sink(self) -> bool {
matches!(self, Self::File | Self::Both)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LogRotation {
Hourly,
Daily,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileLoggingConfig {
pub dir: PathBuf,
pub rotation: LogRotation,
pub retention_days: u64,
pub max_files: usize,
}
impl FileLoggingConfig {
pub fn new(
dir: impl Into<PathBuf>,
rotation: LogRotation,
retention_days: u64,
max_files: usize,
) -> Self {
Self {
dir: dir.into(),
rotation,
retention_days,
max_files,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ServiceObservabilityConfig {
pub log_format: LogFormat,
pub metrics_namespace: &'static str,
pub log_destination: LogDestination,
pub file_logging: Option<FileLoggingConfig>,
pub node_role: Option<String>,
pub instance_id: Option<String>,
}
impl ServiceObservabilityConfig {
@@ -11,6 +59,30 @@ impl ServiceObservabilityConfig {
Self {
log_format,
metrics_namespace,
log_destination: LogDestination::Stdout,
file_logging: None,
node_role: None,
instance_id: None,
}
}
pub const fn with_log_destination(mut self, log_destination: LogDestination) -> Self {
self.log_destination = log_destination;
self
}
pub fn with_file_logging(mut self, file_logging: FileLoggingConfig) -> Self {
self.file_logging = Some(file_logging);
self
}
pub fn with_node_role(mut self, node_role: impl Into<String>) -> Self {
self.node_role = Some(node_role.into());
self
}
pub fn with_instance_id(mut self, instance_id: impl Into<String>) -> Self {
self.instance_id = Some(instance_id.into());
self
}
}

View File

@@ -0,0 +1,36 @@
use std::fmt::Write as _;
use sha2::{Digest, Sha256};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TextPayloadSummary {
pub bytes: usize,
pub sha256: String,
}
pub fn summarize_text_payload(text: &str) -> TextPayloadSummary {
let digest = Sha256::digest(text.as_bytes());
let mut sha256 = String::with_capacity(digest.len() * 2);
for byte in digest {
write!(&mut sha256, "{byte:02x}").expect("writing to string should not fail");
}
TextPayloadSummary {
bytes: text.len(),
sha256,
}
}
#[cfg(test)]
mod tests {
use super::summarize_text_payload;
#[test]
fn summarizes_text_payload_without_exposing_content() {
let summary = summarize_text_payload("secret-body");
assert_eq!(summary.bytes, 11);
assert_eq!(
summary.sha256,
"7c3029502007b2beae470d090221f0a8f7708be361be4662f4b649426e5767b3"
);
}
}

File diff suppressed because it is too large Load Diff