mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-07 18:07:47 +08:00
fix: harden concurrency limits and high-RPM runtime paths
Bound request, stream, queue, and shutdown resource lifetimes. Reduce scheduler and Redis hot-path work and isolate database maintenance. Include regression coverage, load probes, and concurrency audit results.
This commit is contained in:
@@ -35,7 +35,6 @@ use crate::ai_serving::{
|
||||
SkippedLocalExecutionCandidate,
|
||||
};
|
||||
use crate::clock::current_unix_ms;
|
||||
use crate::handlers::shared::provider_pool::read_admin_provider_pool_runtime_state;
|
||||
use crate::handlers::shared::provider_pool::{
|
||||
admin_provider_pool_cache_affinity_enabled, admin_provider_pool_config_from_config_value,
|
||||
};
|
||||
@@ -44,6 +43,9 @@ use crate::handlers::shared::provider_pool::{
|
||||
read_admin_provider_pool_key_cooldown_reason, AdminProviderPoolConfig,
|
||||
AdminProviderPoolRuntimeState, AdminProviderPoolSchedulingPreset,
|
||||
};
|
||||
use crate::handlers::shared::provider_pool::{
|
||||
read_provider_pool_scheduling_runtime_state, read_provider_pool_sticky_bound_key_id,
|
||||
};
|
||||
use crate::handlers::shared::{parse_catalog_auth_config_json, provider_key_health_summary};
|
||||
use crate::maintenance::spawn_pool_quota_probe_replenish_for_request;
|
||||
use crate::orchestration::LocalExecutionCandidateMetadata;
|
||||
@@ -141,7 +143,7 @@ async fn schedule_pool_page_candidates(
|
||||
AdminProviderPoolRuntimeState::default()
|
||||
} else {
|
||||
let runtime_started_at = std::time::Instant::now();
|
||||
let runtime = read_admin_provider_pool_runtime_state(
|
||||
let runtime = read_provider_pool_scheduling_runtime_state(
|
||||
state.app().runtime_state.as_ref(),
|
||||
provider_id.as_str(),
|
||||
&key_ids,
|
||||
@@ -982,15 +984,13 @@ impl<'a> PoolKeyCursor<'a> {
|
||||
if !admin_provider_pool_cache_affinity_enabled(&pool_config) {
|
||||
return None;
|
||||
}
|
||||
let runtime = read_admin_provider_pool_runtime_state(
|
||||
let sticky_key_id = read_provider_pool_sticky_bound_key_id(
|
||||
self.state.app().runtime_state.as_ref(),
|
||||
self.group.candidate.provider_id.as_str(),
|
||||
&[],
|
||||
&pool_config,
|
||||
self.sticky_session_token.as_deref(),
|
||||
)
|
||||
.await;
|
||||
let sticky_key_id = runtime.sticky_bound_key_id?;
|
||||
.await?;
|
||||
if self
|
||||
.routing_overlay
|
||||
.as_ref()
|
||||
@@ -2028,7 +2028,9 @@ mod tests {
|
||||
};
|
||||
use crate::data::GatewayDataState;
|
||||
use crate::handlers::shared::provider_pool::{
|
||||
admin_provider_pool_cache_affinity_enabled, record_admin_provider_pool_error,
|
||||
admin_provider_pool_cache_affinity_enabled, admin_provider_pool_config_from_config_value,
|
||||
read_admin_provider_pool_runtime_state, read_provider_pool_scheduling_runtime_state,
|
||||
record_admin_provider_pool_error, record_admin_provider_pool_success,
|
||||
AdminProviderPoolRuntimeState,
|
||||
};
|
||||
use crate::orchestration::LocalExecutionCandidateMetadata;
|
||||
@@ -2060,6 +2062,111 @@ mod tests {
|
||||
use std::collections::{BTreeMap, BTreeSet, VecDeque};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::test]
|
||||
async fn scheduling_runtime_preserves_pool_ranking_and_cost_rejections() {
|
||||
let runtime = aether_runtime_state::RuntimeState::memory(
|
||||
aether_runtime_state::MemoryRuntimeStateConfig::default(),
|
||||
);
|
||||
let writer_config = admin_provider_pool_config_from_config_value(Some(&json!({
|
||||
"pool_advanced": {
|
||||
"cost_limit_per_key_tokens": 100,
|
||||
"scheduling_presets": [
|
||||
{"preset": "cache_affinity", "enabled": true},
|
||||
{"preset": "latency_first", "enabled": true}
|
||||
]
|
||||
}
|
||||
})))
|
||||
.expect("writer pool config");
|
||||
for (key_id, cost, latency) in [("key-a", 100, 10), ("key-b", 20, 100)] {
|
||||
record_admin_provider_pool_success(
|
||||
&runtime,
|
||||
"provider-pool",
|
||||
key_id,
|
||||
&writer_config,
|
||||
Some(key_id),
|
||||
cost,
|
||||
Some(latency),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
let key_ids = vec!["key-a".to_string(), "key-b".to_string()];
|
||||
for (preset, cost_limit) in [
|
||||
("cache_affinity", None),
|
||||
("priority_first", None),
|
||||
("latency_first", None),
|
||||
("cost_first", None),
|
||||
("quota_balanced", None),
|
||||
("latency_first", Some(100)),
|
||||
] {
|
||||
let provider_config = json!({
|
||||
"pool_advanced": {
|
||||
"cost_limit_per_key_tokens": cost_limit,
|
||||
"scheduling_presets": [{"preset": preset, "enabled": true}]
|
||||
}
|
||||
});
|
||||
let pool_config = admin_provider_pool_config_from_config_value(Some(&provider_config))
|
||||
.expect("reader pool config");
|
||||
let admin = read_admin_provider_pool_runtime_state(
|
||||
&runtime,
|
||||
"provider-pool",
|
||||
&key_ids,
|
||||
&pool_config,
|
||||
Some("key-a"),
|
||||
)
|
||||
.await;
|
||||
let scheduling = read_provider_pool_scheduling_runtime_state(
|
||||
&runtime,
|
||||
"provider-pool",
|
||||
&key_ids,
|
||||
&pool_config,
|
||||
Some("key-a"),
|
||||
)
|
||||
.await;
|
||||
let run = |snapshot| {
|
||||
let candidates = key_ids
|
||||
.iter()
|
||||
.map(|key_id| {
|
||||
sample_eligible_candidate(
|
||||
"provider-pool",
|
||||
"endpoint-1",
|
||||
key_id,
|
||||
10,
|
||||
Some(provider_config.clone()),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let (scheduled, skipped) = apply_local_execution_pool_scheduler_with_runtime_map(
|
||||
candidates,
|
||||
&BTreeMap::from([("provider-pool".to_string(), snapshot)]),
|
||||
&BTreeMap::new(),
|
||||
);
|
||||
(
|
||||
scheduled
|
||||
.into_iter()
|
||||
.map(|item| item.candidate.key_id)
|
||||
.collect::<Vec<_>>(),
|
||||
skipped
|
||||
.into_iter()
|
||||
.map(|item| (item.candidate.key_id, item.skip_reason))
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
};
|
||||
let expected = run(admin);
|
||||
let actual = run(scheduling);
|
||||
assert_eq!(
|
||||
actual, expected,
|
||||
"preset: {preset}, cost limit: {cost_limit:?}"
|
||||
);
|
||||
if cost_limit.is_some() {
|
||||
assert_eq!(actual.0, vec!["key-b"]);
|
||||
assert_eq!(
|
||||
actual.1,
|
||||
vec![("key-a".to_string(), "pool_cost_limit_reached")]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pool_scheduler_groups_interleaved_candidates_and_reorders_internal_keys() {
|
||||
let pool_first = sample_eligible_candidate(
|
||||
|
||||
Reference in New Issue
Block a user