mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
fix(adaptive): 修复 429 计数归零写入及 reset 语义
- sql.rs: UPDATE 时对 concurrent_429_count / rpm_429_count 加 COALESCE(, 0),避免 None 覆写为 NULL - effects.rs: rpm_429_count 始终写入 Some(projection.rpm_429_count),不再过滤零值;新增 unknown-429 场景下零值持久化的单元测试 - adaptive.rs: reset 接口将两个计数字段置为 Some(0) 而非 None,与数据库默认语义对齐;同步修正集成测试断言 - docker-compose.build.yml: 补充 AETHER_GATEWAY_AUTO_PREPARE_DATABASE 默认开启 - README.md: 同步说明 build compose 也已默认开启自动迁移
This commit is contained in:
@@ -134,8 +134,8 @@ impl<'a> AdminAppState<'a> {
|
||||
return Ok(admin_adaptive_key_not_found_response(key_id));
|
||||
};
|
||||
key.learned_rpm_limit = None;
|
||||
key.concurrent_429_count = None;
|
||||
key.rpm_429_count = None;
|
||||
key.concurrent_429_count = Some(0);
|
||||
key.rpm_429_count = Some(0);
|
||||
key.last_429_at_unix_secs = None;
|
||||
key.last_429_type = None;
|
||||
key.adjustment_history = None;
|
||||
|
||||
@@ -300,7 +300,7 @@ async fn record_adaptive_rate_limit_effect(
|
||||
};
|
||||
|
||||
let mut updated_key = current_key.clone();
|
||||
updated_key.rpm_429_count = Some(projection.rpm_429_count).filter(|value| *value > 0);
|
||||
updated_key.rpm_429_count = Some(projection.rpm_429_count);
|
||||
updated_key.learned_rpm_limit = projection.learned_rpm_limit;
|
||||
updated_key.last_429_at_unix_secs = Some(projection.last_429_at_unix_secs);
|
||||
updated_key.last_429_type = Some(projection.last_429_type);
|
||||
@@ -1315,6 +1315,40 @@ mod tests {
|
||||
assert_eq!(stored_key.last_429_type, None);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn adaptive_rate_limit_effect_persists_zero_rpm_count_for_unknown_429() {
|
||||
let mut key = sample_health_key();
|
||||
key.rpm_limit = None;
|
||||
key.learned_rpm_limit = Some(20);
|
||||
let state = adaptive_state_with_request_candidates(key, Vec::new());
|
||||
let plan = sample_plan();
|
||||
|
||||
apply_local_execution_effect(
|
||||
&state,
|
||||
LocalExecutionEffectContext {
|
||||
plan: &plan,
|
||||
report_context: None,
|
||||
},
|
||||
LocalExecutionEffect::AdaptiveRateLimit(LocalAdaptiveRateLimitEffect {
|
||||
status_code: 429,
|
||||
classification: LocalFailoverClassification::RetryStatusCode,
|
||||
headers: None,
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
let stored_key = state
|
||||
.read_provider_catalog_keys_by_ids(std::slice::from_ref(&plan.key_id))
|
||||
.await
|
||||
.expect("provider catalog keys should load")
|
||||
.into_iter()
|
||||
.next()
|
||||
.expect("stored key should exist");
|
||||
assert_eq!(stored_key.rpm_429_count, Some(0));
|
||||
assert_eq!(stored_key.learned_rpm_limit, Some(19));
|
||||
assert_eq!(stored_key.last_429_type.as_deref(), Some("unknown"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn adaptive_success_effect_expands_limit_from_recent_rpm_usage() {
|
||||
let now_unix_secs = chrono::Utc::now().timestamp().max(0) as u64;
|
||||
|
||||
@@ -440,8 +440,8 @@ async fn gateway_resets_admin_adaptive_learning_locally_with_trusted_admin_princ
|
||||
.await
|
||||
.expect("repository query should succeed");
|
||||
assert_eq!(updated[0].learned_rpm_limit, None);
|
||||
assert_eq!(updated[0].concurrent_429_count, None);
|
||||
assert_eq!(updated[0].rpm_429_count, None);
|
||||
assert_eq!(updated[0].concurrent_429_count, Some(0));
|
||||
assert_eq!(updated[0].rpm_429_count, Some(0));
|
||||
assert_eq!(updated[0].adjustment_history, None);
|
||||
|
||||
gateway_handle.abort();
|
||||
|
||||
Reference in New Issue
Block a user