mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-08 02:17:46 +08:00
fix: resolve workspace lint and regression test failures
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use super::{
|
||||
any, build_router_with_state, build_state_with_execution_runtime_override, json, start_server,
|
||||
Arc, Body, Bytes, HeaderValue, Infallible, Json, Mutex, Request, Response, Router, StatusCode,
|
||||
TRACE_ID_HEADER,
|
||||
LOCAL_EXECUTION_RUNTIME_MISS_REASON_HEADER, TRACE_ID_HEADER,
|
||||
};
|
||||
|
||||
use aether_crypto::{encrypt_python_fernet_plaintext, DEVELOPMENT_ENCRYPTION_KEY};
|
||||
@@ -626,7 +626,7 @@ async fn gateway_returns_error_body_when_prefetch_detects_embedded_stream_error_
|
||||
auth_repository,
|
||||
candidate_selection_repository,
|
||||
provider_catalog_repository,
|
||||
request_candidate_repository,
|
||||
Arc::clone(&request_candidate_repository),
|
||||
DEVELOPMENT_ENCRYPTION_KEY,
|
||||
),
|
||||
),
|
||||
@@ -649,17 +649,41 @@ async fn gateway_returns_error_body_when_prefetch_detects_embedded_stream_error_
|
||||
.await
|
||||
.expect("request should succeed");
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_eq!(response.status(), StatusCode::SERVICE_UNAVAILABLE);
|
||||
assert_eq!(
|
||||
response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_TYPE)
|
||||
.and_then(|value| value.to_str().ok()),
|
||||
Some("text/event-stream")
|
||||
Some("application/json")
|
||||
);
|
||||
let body_text = response.text().await.expect("response body should read");
|
||||
assert!(body_text.contains("\"rate_limit_error\""));
|
||||
assert!(body_text.contains("\"slow down\""));
|
||||
assert_eq!(
|
||||
response
|
||||
.headers()
|
||||
.get(LOCAL_EXECUTION_RUNTIME_MISS_REASON_HEADER)
|
||||
.and_then(|value| value.to_str().ok()),
|
||||
Some("execution_runtime_candidates_exhausted")
|
||||
);
|
||||
let body_json: serde_json::Value = response.json().await.expect("response body should parse");
|
||||
assert_eq!(body_json["error"]["type"], "http_error");
|
||||
let stored_candidates = request_candidate_repository
|
||||
.list_by_request_id("trace-openai-chat-stream-prefetch-error-123")
|
||||
.await
|
||||
.expect("request candidate trace should read");
|
||||
let failed_candidate = stored_candidates
|
||||
.iter()
|
||||
.find(|candidate| candidate.status == RequestCandidateStatus::Failed)
|
||||
.expect("prefetched error should mark the attempted candidate as failed");
|
||||
assert!(stored_candidates
|
||||
.iter()
|
||||
.all(|candidate| candidate.status != RequestCandidateStatus::Success));
|
||||
assert_eq!(failed_candidate.status_code, Some(429));
|
||||
assert_eq!(
|
||||
failed_candidate.error_type.as_deref(),
|
||||
Some("rate_limit_error")
|
||||
);
|
||||
assert_eq!(failed_candidate.error_message.as_deref(), Some("slow down"));
|
||||
assert!(failed_candidate.finished_at_unix_ms.is_some());
|
||||
assert_eq!(*public_hits.lock().expect("mutex should lock"), 0);
|
||||
|
||||
gateway_handle.abort();
|
||||
|
||||
@@ -349,7 +349,7 @@ async fn gateway_executes_gemini_chat_stream_via_local_decision_gate_with_local_
|
||||
});
|
||||
let frames = concat!(
|
||||
"{\"type\":\"headers\",\"payload\":{\"kind\":\"headers\",\"status_code\":200,\"headers\":{\"content-type\":\"text/event-stream\"}}}\n",
|
||||
"{\"type\":\"data\",\"payload\":{\"kind\":\"data\",\"text\":\"data: {\\\"candidates\\\":[]}\\n\\n\"}}\n",
|
||||
"{\"type\":\"data\",\"payload\":{\"kind\":\"data\",\"text\":\"data: {\\\"candidates\\\":[{\\\"content\\\":{\\\"parts\\\":[{\\\"text\\\":\\\"ok\\\"}]},\\\"finishReason\\\":\\\"STOP\\\"}]}\\n\\n\"}}\n",
|
||||
"{\"type\":\"telemetry\",\"payload\":{\"kind\":\"telemetry\",\"telemetry\":{\"elapsed_ms\":33,\"upstream_bytes\":26}}}\n",
|
||||
"{\"type\":\"eof\",\"payload\":{\"kind\":\"eof\"}}\n"
|
||||
);
|
||||
@@ -419,7 +419,7 @@ async fn gateway_executes_gemini_chat_stream_via_local_decision_gate_with_local_
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_eq!(
|
||||
strip_sse_keepalive_comments(&response.text().await.expect("body should read")),
|
||||
"data: {\"candidates\":[]}\n\n"
|
||||
"data: {\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"ok\"}]},\"finishReason\":\"STOP\"}]}\n\n"
|
||||
);
|
||||
|
||||
let seen_execution_runtime_request = seen_execution_runtime
|
||||
|
||||
@@ -326,7 +326,7 @@ async fn gateway_executes_gemini_cli_stream_via_local_decision_gate_with_local_s
|
||||
});
|
||||
let frames = concat!(
|
||||
"{\"type\":\"headers\",\"payload\":{\"kind\":\"headers\",\"status_code\":200,\"headers\":{\"content-type\":\"text/event-stream\"}}}\n",
|
||||
"{\"type\":\"data\",\"payload\":{\"kind\":\"data\",\"text\":\"data: {\\\"candidates\\\":[]}\\n\\n\"}}\n",
|
||||
"{\"type\":\"data\",\"payload\":{\"kind\":\"data\",\"text\":\"data: {\\\"candidates\\\":[{\\\"content\\\":{\\\"parts\\\":[{\\\"text\\\":\\\"ok\\\"}]},\\\"finishReason\\\":\\\"STOP\\\"}]}\\n\\n\"}}\n",
|
||||
"{\"type\":\"telemetry\",\"payload\":{\"kind\":\"telemetry\",\"telemetry\":{\"elapsed_ms\":34,\"upstream_bytes\":26}}}\n",
|
||||
"{\"type\":\"eof\",\"payload\":{\"kind\":\"eof\"}}\n"
|
||||
);
|
||||
@@ -396,7 +396,7 @@ async fn gateway_executes_gemini_cli_stream_via_local_decision_gate_with_local_s
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_eq!(
|
||||
strip_sse_keepalive_comments(&response.text().await.expect("body should read")),
|
||||
"data: {\"candidates\":[]}\n\n"
|
||||
"data: {\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"ok\"}]},\"finishReason\":\"STOP\"}]}\n\n"
|
||||
);
|
||||
|
||||
let seen_execution_runtime_request = seen_execution_runtime
|
||||
@@ -846,7 +846,7 @@ async fn gateway_executes_gemini_cli_stream_via_local_decision_gate_after_oauth_
|
||||
});
|
||||
let frames = concat!(
|
||||
"{\"type\":\"headers\",\"payload\":{\"kind\":\"headers\",\"status_code\":200,\"headers\":{\"content-type\":\"text/event-stream\"}}}\n",
|
||||
"{\"type\":\"data\",\"payload\":{\"kind\":\"data\",\"text\":\"data: {\\\"response\\\":{\\\"candidates\\\":[]},\\\"remainingCredits\\\":42,\\\"consumedCredits\\\":1,\\\"traceId\\\":\\\"trace-upstream-1\\\"}\\n\\n\"}}\n",
|
||||
"{\"type\":\"data\",\"payload\":{\"kind\":\"data\",\"text\":\"data: {\\\"response\\\":{\\\"candidates\\\":[{\\\"content\\\":{\\\"parts\\\":[{\\\"text\\\":\\\"ok\\\"}]},\\\"finishReason\\\":\\\"STOP\\\"}]},\\\"remainingCredits\\\":42,\\\"consumedCredits\\\":1,\\\"traceId\\\":\\\"trace-upstream-1\\\"}\\n\\n\"}}\n",
|
||||
"{\"type\":\"telemetry\",\"payload\":{\"kind\":\"telemetry\",\"telemetry\":{\"elapsed_ms\":34,\"upstream_bytes\":26}}}\n",
|
||||
"{\"type\":\"eof\",\"payload\":{\"kind\":\"eof\"}}\n"
|
||||
);
|
||||
@@ -934,7 +934,7 @@ async fn gateway_executes_gemini_cli_stream_via_local_decision_gate_after_oauth_
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_eq!(
|
||||
strip_sse_keepalive_comments(&response.text().await.expect("body should read")),
|
||||
"data: {\"candidates\":[]}\n\n"
|
||||
"data: {\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"ok\"}]},\"finishReason\":\"STOP\"}]}\n\n"
|
||||
);
|
||||
|
||||
let seen_refresh_request = seen_refresh
|
||||
@@ -1354,7 +1354,7 @@ async fn gateway_executes_vertex_ai_gemini_cli_stream_via_local_decision_gate_wi
|
||||
});
|
||||
let frames = concat!(
|
||||
"{\"type\":\"headers\",\"payload\":{\"kind\":\"headers\",\"status_code\":200,\"headers\":{\"content-type\":\"text/event-stream\"}}}\n",
|
||||
"{\"type\":\"data\",\"payload\":{\"kind\":\"data\",\"text\":\"data: {\\\"candidates\\\":[]}\\n\\n\"}}\n",
|
||||
"{\"type\":\"data\",\"payload\":{\"kind\":\"data\",\"text\":\"data: {\\\"candidates\\\":[{\\\"content\\\":{\\\"parts\\\":[{\\\"text\\\":\\\"ok\\\"}]},\\\"finishReason\\\":\\\"STOP\\\"}]}\\n\\n\"}}\n",
|
||||
"{\"type\":\"telemetry\",\"payload\":{\"kind\":\"telemetry\",\"telemetry\":{\"elapsed_ms\":34,\"upstream_bytes\":26}}}\n",
|
||||
"{\"type\":\"eof\",\"payload\":{\"kind\":\"eof\"}}\n"
|
||||
);
|
||||
@@ -1422,7 +1422,7 @@ async fn gateway_executes_vertex_ai_gemini_cli_stream_via_local_decision_gate_wi
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_eq!(
|
||||
strip_sse_keepalive_comments(&response.text().await.expect("body should read")),
|
||||
"data: {\"candidates\":[]}\n\n"
|
||||
"data: {\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"ok\"}]},\"finishReason\":\"STOP\"}]}\n\n"
|
||||
);
|
||||
|
||||
let seen_execution_runtime_request = seen_execution_runtime
|
||||
|
||||
@@ -96,12 +96,11 @@ fn aether_data_backend_pool_modules_do_not_own_maintenance_sql() {
|
||||
#[test]
|
||||
fn wallet_maintenance_sql_is_partitioned_by_driver() {
|
||||
let facade = read_workspace_file("crates/aether-data/runtime/src/backend/wallet.rs");
|
||||
for module in ["mod postgres;"] {
|
||||
assert!(
|
||||
facade.contains(module),
|
||||
"wallet facade should declare {module}"
|
||||
);
|
||||
}
|
||||
let module = "mod postgres;";
|
||||
assert!(
|
||||
facade.contains(module),
|
||||
"wallet facade should declare {module}"
|
||||
);
|
||||
for forbidden in [
|
||||
"sqlx::",
|
||||
"PostgresBackend",
|
||||
@@ -115,24 +114,22 @@ fn wallet_maintenance_sql_is_partitioned_by_driver() {
|
||||
);
|
||||
}
|
||||
|
||||
for (driver, backend) in [("postgres", "PostgresBackend")] {
|
||||
let path = format!("crates/aether-data/runtime/src/backend/wallet/{driver}.rs");
|
||||
let source = read_workspace_file(&path);
|
||||
assert!(source.contains(&format!("impl {backend}")));
|
||||
assert!(source.contains("aggregate_wallet_daily_usage"));
|
||||
assert!(source.contains("sqlx::query"));
|
||||
}
|
||||
let (driver, backend) = ("postgres", "PostgresBackend");
|
||||
let path = format!("crates/aether-data/runtime/src/backend/wallet/{driver}.rs");
|
||||
let source = read_workspace_file(&path);
|
||||
assert!(source.contains(&format!("impl {backend}")));
|
||||
assert!(source.contains("aggregate_wallet_daily_usage"));
|
||||
assert!(source.contains("sqlx::query"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn table_maintenance_is_partitioned_for_each_driver() {
|
||||
let facade = read_workspace_file("crates/aether-data/runtime/src/backend/maintenance.rs");
|
||||
for module in ["mod postgres;"] {
|
||||
assert!(
|
||||
facade.contains(module),
|
||||
"maintenance facade should declare {module}"
|
||||
);
|
||||
}
|
||||
let module = "mod postgres;";
|
||||
assert!(
|
||||
facade.contains(module),
|
||||
"maintenance facade should declare {module}"
|
||||
);
|
||||
for forbidden in [
|
||||
"impl PostgresBackend",
|
||||
"VACUUM ANALYZE",
|
||||
@@ -156,12 +153,11 @@ fn table_maintenance_is_partitioned_for_each_driver() {
|
||||
#[test]
|
||||
fn system_driver_database_operations_are_partitioned() {
|
||||
let facade = read_workspace_file("crates/aether-data/runtime/src/backend/system.rs");
|
||||
for module in ["mod postgres;"] {
|
||||
assert!(
|
||||
facade.contains(module),
|
||||
"system facade should declare {module}"
|
||||
);
|
||||
}
|
||||
let module = "mod postgres;";
|
||||
assert!(
|
||||
facade.contains(module),
|
||||
"system facade should declare {module}"
|
||||
);
|
||||
for forbidden in [
|
||||
"impl PostgresBackend",
|
||||
"fn map_postgres_stats_daily_aggregate(",
|
||||
@@ -1521,12 +1517,11 @@ fn lifecycle_migrations_are_partitioned_by_driver() {
|
||||
types.contains(required),
|
||||
"migrate/types.rs should own {required}"
|
||||
);
|
||||
for forbidden in ["PgPool"] {
|
||||
assert!(
|
||||
!types.contains(forbidden),
|
||||
"migrate/types.rs should remain driver-independent from {forbidden}"
|
||||
);
|
||||
}
|
||||
let forbidden = "PgPool";
|
||||
assert!(
|
||||
!types.contains(forbidden),
|
||||
"migrate/types.rs should remain driver-independent from {forbidden}"
|
||||
);
|
||||
|
||||
let postgres =
|
||||
read_workspace_file("crates/aether-data/runtime/src/lifecycle/migrate/postgres.rs");
|
||||
@@ -1905,12 +1900,11 @@ fn gateway_system_config_types_are_owned_by_aether_data() {
|
||||
}
|
||||
let data_backends =
|
||||
read_workspace_file("crates/aether-data/runtime/src/backend/maintenance.rs");
|
||||
for pattern in ["postgres.list_system_config_entries().await"] {
|
||||
assert!(
|
||||
data_backends.contains(pattern),
|
||||
"aether-data backends should own driver-specific system config dispatch {pattern}"
|
||||
);
|
||||
}
|
||||
let pattern = "postgres.list_system_config_entries().await";
|
||||
assert!(
|
||||
data_backends.contains(pattern),
|
||||
"aether-data backends should own driver-specific system config dispatch {pattern}"
|
||||
);
|
||||
for pattern in [
|
||||
"|(key, value, description, updated_at_unix_secs)|",
|
||||
"Ok((0, 0, 0, 0))",
|
||||
|
||||
@@ -3705,9 +3705,9 @@ async fn gateway_completes_admin_provider_oauth_key_locally_with_trusted_admin_p
|
||||
scores[0].hard_state.schedulable(),
|
||||
"OAuth completion should replace AuthInvalid with a schedulable score"
|
||||
);
|
||||
let decrypted_api_key = decrypt_persisted_provider_api_key(&persisted);
|
||||
let decrypted_api_key = decrypt_persisted_provider_api_key(persisted);
|
||||
assert_eq!(decrypted_api_key, "new-codex-access-token");
|
||||
let decrypted_auth_config = decrypt_persisted_provider_auth_config(&persisted);
|
||||
let decrypted_auth_config = decrypt_persisted_provider_auth_config(persisted);
|
||||
let auth_config: serde_json::Value =
|
||||
serde_json::from_str(&decrypted_auth_config).expect("auth config json should parse");
|
||||
assert_eq!(auth_config["provider_type"], "codex");
|
||||
|
||||
@@ -3834,12 +3834,12 @@ async fn gateway_overwrites_oauth_provider_key_credentials_from_admin_system_imp
|
||||
Some(&Value::Null)
|
||||
);
|
||||
assert_eq!(
|
||||
decrypt_test_provider_catalog_credential(&key, ProviderCatalogCredentialField::ApiKey,),
|
||||
decrypt_test_provider_catalog_credential(key, ProviderCatalogCredentialField::ApiKey,),
|
||||
"oauth-access-token-new"
|
||||
);
|
||||
|
||||
let auth_config =
|
||||
decrypt_test_provider_catalog_credential(&key, ProviderCatalogCredentialField::AuthConfig);
|
||||
decrypt_test_provider_catalog_credential(key, ProviderCatalogCredentialField::AuthConfig);
|
||||
let auth_config: Value =
|
||||
serde_json::from_str(&auth_config).expect("oauth auth config json should parse");
|
||||
assert_eq!(auth_config["provider_type"], "codex");
|
||||
|
||||
@@ -2659,9 +2659,9 @@ fn set_test_env_var(key: &'static str, value: &str) -> TestEnvVarGuard {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn payment_callback_env_lock() -> &'static std::sync::Mutex<()> {
|
||||
static LOCK: std::sync::OnceLock<std::sync::Mutex<()>> = std::sync::OnceLock::new();
|
||||
LOCK.get_or_init(|| std::sync::Mutex::new(()))
|
||||
fn payment_callback_env_lock() -> &'static tokio::sync::Mutex<()> {
|
||||
static LOCK: tokio::sync::Mutex<()> = tokio::sync::Mutex::const_new(());
|
||||
&LOCK
|
||||
}
|
||||
|
||||
const TEST_PAYMENT_CALLBACK_SECRET: &str = "test-callback-secret-0123456789abcdef";
|
||||
@@ -11875,9 +11875,7 @@ async fn gateway_does_not_report_logout_success_when_session_revoke_is_rejected(
|
||||
|
||||
#[tokio::test]
|
||||
async fn gateway_handles_payment_callback_route_locally_without_proxying_upstream() {
|
||||
let _env_lock = payment_callback_env_lock()
|
||||
.lock()
|
||||
.expect("payment callback test env lock should not be poisoned");
|
||||
let _env_lock = payment_callback_env_lock().lock().await;
|
||||
let _secret_guard = set_test_env_var("PAYMENT_CALLBACK_SECRET", TEST_PAYMENT_CALLBACK_SECRET);
|
||||
let now = Utc::now();
|
||||
let user = StoredUserAuthRecord::new(
|
||||
@@ -12020,9 +12018,7 @@ async fn gateway_handles_payment_callback_route_locally_without_proxying_upstrea
|
||||
|
||||
#[tokio::test]
|
||||
async fn gateway_rejects_payment_callback_with_mismatched_payment_method_locally() {
|
||||
let _env_lock = payment_callback_env_lock()
|
||||
.lock()
|
||||
.expect("payment callback test env lock should not be poisoned");
|
||||
let _env_lock = payment_callback_env_lock().lock().await;
|
||||
let _secret_guard = set_test_env_var("PAYMENT_CALLBACK_SECRET", TEST_PAYMENT_CALLBACK_SECRET);
|
||||
let now = Utc::now();
|
||||
let user = StoredUserAuthRecord::new(
|
||||
|
||||
@@ -1076,7 +1076,7 @@ async fn gateway_forwards_public_request_to_remote_tunnel_owner_before_fallback_
|
||||
let provider_catalog_repository = Arc::new(InMemoryProviderCatalogReadRepository::seed(
|
||||
vec![sample_provider_with_request_timeout(
|
||||
"provider-owner",
|
||||
Some(0.1),
|
||||
Some(2.0),
|
||||
)],
|
||||
vec![sample_endpoint("endpoint-owner", "provider-owner")],
|
||||
vec![sample_bound_key(
|
||||
|
||||
@@ -1100,7 +1100,7 @@ async fn sync_transport_error_policy_stops_or_retries_candidates_end_to_end_impl
|
||||
let mut second_candidate = sample_local_openai_candidate_row();
|
||||
second_candidate.key_id = "key-openai-usage-local-2".to_string();
|
||||
second_candidate.key_name = "secondary".to_string();
|
||||
second_candidate.key_internal_priority = second_candidate.key_internal_priority - 1;
|
||||
second_candidate.key_internal_priority -= 1;
|
||||
let candidate_selection_repository =
|
||||
Arc::new(InMemoryMinimalCandidateSelectionReadRepository::seed(vec![
|
||||
sample_local_openai_candidate_row(),
|
||||
|
||||
Reference in New Issue
Block a user