Fix provider deletion cleanup

This commit is contained in:
elky
2026-06-12 16:25:11 +08:00
parent 30b545785f
commit 308cc88ef7
17 changed files with 385 additions and 84 deletions
@@ -117,6 +117,48 @@ fn admin_provider_oauth_complete_dispatch_remains_thin() {
}
}
#[test]
fn postgres_provider_cleanup_preserves_usage_history() {
let postgres_provider_catalog =
read_workspace_file("crates/aether-data/src/repository/provider_catalog/postgres.rs");
for forbidden in [
"UPDATE usage SET provider_id = NULL",
"UPDATE usage SET provider_endpoint_id = NULL",
"UPDATE usage SET provider_api_key_id = NULL",
] {
assert!(
!postgres_provider_catalog.contains(forbidden),
"provider cleanup must not rewrite usage history with {forbidden}"
);
}
}
#[test]
fn provider_cleanup_keeps_common_backends_in_sync() {
for path in [
"crates/aether-data/src/repository/provider_catalog/postgres.rs",
"crates/aether-data/src/repository/provider_catalog/mysql.rs",
"crates/aether-data/src/repository/provider_catalog/sqlite.rs",
] {
let source = read_workspace_file(path);
for required in [
"UPDATE user_preferences SET default_provider_id = NULL WHERE default_provider_id =",
"UPDATE video_tasks SET provider_id = NULL WHERE provider_id =",
"DELETE FROM request_candidates WHERE provider_id =",
"UPDATE video_tasks SET endpoint_id = NULL WHERE endpoint_id =",
"DELETE FROM request_candidates WHERE endpoint_id =",
"DELETE FROM gemini_file_mappings WHERE key_id =",
"UPDATE video_tasks SET key_id = NULL WHERE key_id =",
] {
assert!(
source.contains(required),
"{path} should keep provider cleanup behavior in sync with {required}"
);
}
}
}
#[test]
fn admin_provider_oauth_complete_helpers_are_split() {
let complete_mod = read_workspace_file(
@@ -1703,6 +1703,52 @@ async fn gateway_submits_admin_provider_delete_task_locally_with_trusted_admin_p
upstream_handle.abort();
}
#[test]
fn provider_delete_task_reservation_reuses_active_provider_task() {
let state = AppState::new().expect("gateway should build");
let first = crate::LocalProviderDeleteTaskState {
task_id: "task-first".to_string(),
provider_id: "provider-openai".to_string(),
status: "pending".to_string(),
stage: "queued".to_string(),
total_keys: 0,
deleted_keys: 0,
total_endpoints: 0,
deleted_endpoints: 0,
message: "delete task submitted".to_string(),
};
let second = crate::LocalProviderDeleteTaskState {
task_id: "task-second".to_string(),
provider_id: "provider-openai".to_string(),
status: "pending".to_string(),
stage: "queued".to_string(),
total_keys: 0,
deleted_keys: 0,
total_endpoints: 0,
deleted_endpoints: 0,
message: "delete task submitted".to_string(),
};
assert_eq!(
state.reserve_provider_delete_task(first.clone()).task_id,
"task-first"
);
assert_eq!(
state.reserve_provider_delete_task(second.clone()).task_id,
"task-first"
);
state.put_provider_delete_task(crate::LocalProviderDeleteTaskState {
status: "completed".to_string(),
stage: "completed".to_string(),
..first
});
assert_eq!(
state.reserve_provider_delete_task(second).task_id,
"task-second"
);
}
#[tokio::test]
async fn local_admin_provider_delete_task_status_attaches_audit_only_for_terminal_states() {
let mut completed_state = AppState::new().expect("gateway should build");