mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-09 18:59:50 +08:00
feat(gateway): 重构 usage 数据层、迁移系统与系统导入
数据库迁移: - 引入 baseline v2 bootstrap,空库首次启动自动初始化 - 服务启动不再自动执行迁移,需显式 `--migrate` 运行 - 新增 pending migration 检测,schema 落后时拒绝启动 Usage 数据层: - usage body 存储外部化为独立 blob 表 - 新增 HTTP audit 表拆分存储请求/响应头与 body ref - 后台清理任务支持 legacy body ref 元数据迁移 - usage runtime 写入迁移到专用 tokio runtime(独立线程池, 8MB 栈) 系统导入/导出: - 支持用户、API Keys、钱包数据的完整导入 - 兼容 legacy 与 v1.3+ 两种导出格式 其他改进: - executor outcome 增加 runtime miss 诊断上下文 - 主 tokio runtime 栈大小调整为 8MB - 前端 provider 管理支持 base URL 配置 - dev.sh 支持 --migrate 参数
This commit is contained in:
@@ -252,6 +252,28 @@ impl AppState {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub async fn pending_postgres_migrations(
|
||||
&self,
|
||||
) -> Result<Option<Vec<aether_data::migrate::PendingMigrationInfo>>, sqlx::migrate::MigrateError>
|
||||
{
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(None);
|
||||
};
|
||||
Ok(Some(aether_data::migrate::pending_migrations(&pool).await?))
|
||||
}
|
||||
|
||||
pub async fn prepare_postgres_for_startup(
|
||||
&self,
|
||||
) -> Result<Option<Vec<aether_data::migrate::PendingMigrationInfo>>, sqlx::migrate::MigrateError>
|
||||
{
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(None);
|
||||
};
|
||||
Ok(Some(
|
||||
aether_data::migrate::prepare_database_for_startup(&pool).await?,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn with_video_task_poller_config(mut self, interval: Duration, batch_size: usize) -> Self {
|
||||
self.video_task_poller = Some(VideoTaskPollerConfig {
|
||||
interval,
|
||||
@@ -559,10 +581,17 @@ impl AppState {
|
||||
trace_id: &str,
|
||||
diagnostic: LocalExecutionRuntimeMissDiagnostic,
|
||||
) {
|
||||
self.local_execution_runtime_miss_diagnostics
|
||||
let mut diagnostics = self
|
||||
.local_execution_runtime_miss_diagnostics
|
||||
.lock()
|
||||
.expect("local execution runtime miss diagnostics should lock")
|
||||
.insert(trace_id.to_string(), diagnostic);
|
||||
.expect("local execution runtime miss diagnostics should lock");
|
||||
if diagnostics
|
||||
.get(trace_id)
|
||||
.is_some_and(|existing| should_preserve_runtime_miss_diagnostic(existing, &diagnostic))
|
||||
{
|
||||
return;
|
||||
}
|
||||
diagnostics.insert(trace_id.to_string(), diagnostic);
|
||||
}
|
||||
|
||||
pub(crate) fn mutate_local_execution_runtime_miss_diagnostic<F>(
|
||||
@@ -581,6 +610,17 @@ impl AppState {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn local_execution_runtime_miss_diagnostic_has_candidate_signal(
|
||||
&self,
|
||||
trace_id: &str,
|
||||
) -> bool {
|
||||
self.local_execution_runtime_miss_diagnostics
|
||||
.lock()
|
||||
.expect("local execution runtime miss diagnostics should lock")
|
||||
.get(trace_id)
|
||||
.is_some_and(runtime_miss_diagnostic_has_candidate_signal)
|
||||
}
|
||||
|
||||
pub(crate) fn take_local_execution_runtime_miss_diagnostic(
|
||||
&self,
|
||||
trace_id: &str,
|
||||
@@ -735,3 +775,19 @@ impl AppState {
|
||||
tasks
|
||||
}
|
||||
}
|
||||
|
||||
fn should_preserve_runtime_miss_diagnostic(
|
||||
existing: &LocalExecutionRuntimeMissDiagnostic,
|
||||
next: &LocalExecutionRuntimeMissDiagnostic,
|
||||
) -> bool {
|
||||
runtime_miss_diagnostic_has_candidate_signal(existing)
|
||||
&& !runtime_miss_diagnostic_has_candidate_signal(next)
|
||||
}
|
||||
|
||||
fn runtime_miss_diagnostic_has_candidate_signal(
|
||||
diagnostic: &LocalExecutionRuntimeMissDiagnostic,
|
||||
) -> bool {
|
||||
diagnostic.candidate_count.unwrap_or(0) > 0
|
||||
|| diagnostic.skipped_candidate_count.unwrap_or(0) > 0
|
||||
|| !diagnostic.skip_reasons.is_empty()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user