mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-12 22:20:19 +08:00
Improve gateway transport and usage runtime
This commit is contained in:
+154
-2
@@ -17,11 +17,16 @@ use sha2::Digest as _;
|
||||
use crate::ai_serving::{
|
||||
EligibleLocalExecutionCandidate, GatewayAuthApiKeySnapshot, SkippedLocalExecutionCandidate,
|
||||
};
|
||||
use crate::data::candidate_selection::RequestedModelCandidateRowsPage;
|
||||
|
||||
const DEFAULT_CANDIDATE_PAGE_CACHE_TTL_MS: u64 = 250;
|
||||
const MIN_CANDIDATE_PAGE_CACHE_TTL_MS: u64 = 50;
|
||||
const MAX_CANDIDATE_PAGE_CACHE_TTL_MS: u64 = 1_000;
|
||||
const CANDIDATE_PAGE_CACHE_TTL_ENV: &str = "AETHER_GATEWAY_CANDIDATE_PAGE_CACHE_TTL_MS";
|
||||
const DEFAULT_CANDIDATE_PAGE_CACHE_STALE_TTL_MS: u64 = 300_000;
|
||||
const MIN_CANDIDATE_PAGE_CACHE_STALE_TTL_MS: u64 = 1_000;
|
||||
const MAX_CANDIDATE_PAGE_CACHE_STALE_TTL_MS: u64 = 300_000;
|
||||
const CANDIDATE_PAGE_CACHE_STALE_TTL_ENV: &str = "AETHER_GATEWAY_CANDIDATE_PAGE_CACHE_STALE_TTL_MS";
|
||||
|
||||
pub(crate) type CandidatePageSnapshot = AiCandidatePreselectionOutcome<
|
||||
SchedulerMinimalCandidateSelectionCandidate,
|
||||
@@ -31,6 +36,9 @@ pub(crate) type CandidatePageSnapshot = AiCandidatePreselectionOutcome<
|
||||
pub(crate) type CandidatePageCache =
|
||||
super::ValueCache<CandidatePageCacheKey, Arc<CandidatePageSnapshot>>;
|
||||
|
||||
pub(crate) type CandidateRowPageCache =
|
||||
super::ValueCache<CandidateRowPageCacheKey, Arc<RequestedModelCandidateRowsPage>>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct CandidateResolvedPageSnapshot {
|
||||
pub(crate) candidates: Vec<EligibleLocalExecutionCandidate>,
|
||||
@@ -54,6 +62,21 @@ struct CandidatePageCacheMetrics {
|
||||
resolve_load_total: AtomicU64,
|
||||
resolve_follower_wait_total: AtomicU64,
|
||||
resolve_miss_total: AtomicU64,
|
||||
row_hit_total: AtomicU64,
|
||||
row_load_total: AtomicU64,
|
||||
row_follower_wait_total: AtomicU64,
|
||||
row_miss_total: AtomicU64,
|
||||
row_none_total: AtomicU64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct CandidateRowPageCacheKey {
|
||||
api_format: String,
|
||||
requested_model_name: String,
|
||||
requested_name: String,
|
||||
offset: u32,
|
||||
limit: u32,
|
||||
enable_model_directives: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
@@ -83,6 +106,26 @@ pub(crate) struct CandidateResolvedPageCacheKey {
|
||||
resolution_mode: &'static str,
|
||||
}
|
||||
|
||||
impl CandidateRowPageCacheKey {
|
||||
pub(crate) fn new(
|
||||
api_format: &str,
|
||||
requested_model_name: &str,
|
||||
requested_name: &str,
|
||||
offset: u32,
|
||||
limit: u32,
|
||||
enable_model_directives: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
api_format: normalize_api_format(api_format),
|
||||
requested_model_name: normalize_text_key(requested_model_name),
|
||||
requested_name: normalize_text_key(requested_name),
|
||||
offset,
|
||||
limit,
|
||||
enable_model_directives,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CandidatePageCacheKey {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn new(
|
||||
@@ -177,8 +220,16 @@ pub(crate) fn candidate_page_cache_ttl_from_env() -> Duration {
|
||||
}
|
||||
|
||||
pub(crate) fn candidate_page_cache_stale_ttl(ttl: Duration) -> Duration {
|
||||
let stale_ttl = ttl.saturating_mul(8);
|
||||
stale_ttl.min(Duration::from_secs(2)).max(ttl)
|
||||
let stale_ttl_ms = std::env::var(CANDIDATE_PAGE_CACHE_STALE_TTL_ENV)
|
||||
.ok()
|
||||
.and_then(|value| value.trim().parse::<u64>().ok())
|
||||
.filter(|value| *value > 0)
|
||||
.unwrap_or(DEFAULT_CANDIDATE_PAGE_CACHE_STALE_TTL_MS)
|
||||
.clamp(
|
||||
MIN_CANDIDATE_PAGE_CACHE_STALE_TTL_MS,
|
||||
MAX_CANDIDATE_PAGE_CACHE_STALE_TTL_MS,
|
||||
);
|
||||
Duration::from_millis(stale_ttl_ms).max(ttl)
|
||||
}
|
||||
|
||||
pub(crate) fn record_candidate_page_cache_hit() {
|
||||
@@ -235,6 +286,36 @@ pub(crate) fn record_candidate_page_resolve_cache_follower_wait() {
|
||||
.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub(crate) fn record_candidate_row_page_cache_hit() {
|
||||
CANDIDATE_PAGE_CACHE_METRICS
|
||||
.row_hit_total
|
||||
.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub(crate) fn record_candidate_row_page_cache_miss() {
|
||||
CANDIDATE_PAGE_CACHE_METRICS
|
||||
.row_miss_total
|
||||
.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub(crate) fn record_candidate_row_page_cache_load() {
|
||||
CANDIDATE_PAGE_CACHE_METRICS
|
||||
.row_load_total
|
||||
.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub(crate) fn record_candidate_row_page_cache_follower_wait() {
|
||||
CANDIDATE_PAGE_CACHE_METRICS
|
||||
.row_follower_wait_total
|
||||
.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub(crate) fn record_candidate_row_page_cache_none() {
|
||||
CANDIDATE_PAGE_CACHE_METRICS
|
||||
.row_none_total
|
||||
.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub(crate) fn candidate_page_cache_metric_samples() -> Vec<MetricSample> {
|
||||
vec![
|
||||
MetricSample::new(
|
||||
@@ -309,6 +390,46 @@ pub(crate) fn candidate_page_cache_metric_samples() -> Vec<MetricSample> {
|
||||
.resolve_follower_wait_total
|
||||
.load(Ordering::Relaxed),
|
||||
),
|
||||
MetricSample::new(
|
||||
"candidate_row_page_cache_hit_total",
|
||||
"Total candidate DB row page cache hits.",
|
||||
MetricKind::Counter,
|
||||
CANDIDATE_PAGE_CACHE_METRICS
|
||||
.row_hit_total
|
||||
.load(Ordering::Relaxed),
|
||||
),
|
||||
MetricSample::new(
|
||||
"candidate_row_page_cache_miss_total",
|
||||
"Total candidate DB row page cache misses before singleflight registration.",
|
||||
MetricKind::Counter,
|
||||
CANDIDATE_PAGE_CACHE_METRICS
|
||||
.row_miss_total
|
||||
.load(Ordering::Relaxed),
|
||||
),
|
||||
MetricSample::new(
|
||||
"candidate_row_page_cache_load_total",
|
||||
"Total candidate DB row page cache loader executions.",
|
||||
MetricKind::Counter,
|
||||
CANDIDATE_PAGE_CACHE_METRICS
|
||||
.row_load_total
|
||||
.load(Ordering::Relaxed),
|
||||
),
|
||||
MetricSample::new(
|
||||
"candidate_row_page_cache_follower_wait_total",
|
||||
"Total candidate DB row page cache requests that waited for another loader.",
|
||||
MetricKind::Counter,
|
||||
CANDIDATE_PAGE_CACHE_METRICS
|
||||
.row_follower_wait_total
|
||||
.load(Ordering::Relaxed),
|
||||
),
|
||||
MetricSample::new(
|
||||
"candidate_row_page_cache_none_total",
|
||||
"Total candidate DB row page cache lookups that resolved to no rows.",
|
||||
MetricKind::Counter,
|
||||
CANDIDATE_PAGE_CACHE_METRICS
|
||||
.row_none_total
|
||||
.load(Ordering::Relaxed),
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -371,6 +492,9 @@ mod tests {
|
||||
use super::*;
|
||||
use aether_data::repository::auth::ResolvedAuthApiKeySnapshot;
|
||||
use serde_json::json;
|
||||
use std::sync::Mutex;
|
||||
|
||||
static ENV_LOCK: Mutex<()> = Mutex::new(());
|
||||
|
||||
fn auth_snapshot(user_id: &str, api_key_id: &str) -> ResolvedAuthApiKeySnapshot {
|
||||
ResolvedAuthApiKeySnapshot {
|
||||
@@ -401,6 +525,34 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn candidate_page_cache_stale_ttl_defaults_longer_than_burst_gap() {
|
||||
let _guard = ENV_LOCK.lock().expect("env lock poisoned");
|
||||
std::env::remove_var(CANDIDATE_PAGE_CACHE_STALE_TTL_ENV);
|
||||
|
||||
assert_eq!(
|
||||
candidate_page_cache_stale_ttl(Duration::from_millis(250)),
|
||||
Duration::from_millis(DEFAULT_CANDIDATE_PAGE_CACHE_STALE_TTL_MS)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn candidate_page_cache_stale_ttl_respects_env_and_never_under_fresh_ttl() {
|
||||
let _guard = ENV_LOCK.lock().expect("env lock poisoned");
|
||||
std::env::set_var(CANDIDATE_PAGE_CACHE_STALE_TTL_ENV, "100");
|
||||
assert_eq!(
|
||||
candidate_page_cache_stale_ttl(Duration::from_millis(2_500)),
|
||||
Duration::from_millis(2_500)
|
||||
);
|
||||
|
||||
std::env::set_var(CANDIDATE_PAGE_CACHE_STALE_TTL_ENV, "60000");
|
||||
assert_eq!(
|
||||
candidate_page_cache_stale_ttl(Duration::from_millis(250)),
|
||||
Duration::from_secs(60)
|
||||
);
|
||||
std::env::remove_var(CANDIDATE_PAGE_CACHE_STALE_TTL_ENV);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn candidate_page_cache_key_isolates_auth_model_format_and_capabilities() {
|
||||
let auth_a = auth_snapshot("user-a", "key-a");
|
||||
|
||||
Vendored
+5
-2
@@ -20,8 +20,11 @@ pub(crate) use candidate_page::{
|
||||
record_candidate_page_cache_miss, record_candidate_page_cache_none,
|
||||
record_candidate_page_resolve_cache_follower_wait, record_candidate_page_resolve_cache_hit,
|
||||
record_candidate_page_resolve_cache_load, record_candidate_page_resolve_cache_miss,
|
||||
CandidatePageCache, CandidatePageCacheKey, CandidatePageSnapshot, CandidateResolvedPageCache,
|
||||
CandidateResolvedPageCacheKey, CandidateResolvedPageSnapshot,
|
||||
record_candidate_row_page_cache_follower_wait, record_candidate_row_page_cache_hit,
|
||||
record_candidate_row_page_cache_load, record_candidate_row_page_cache_miss,
|
||||
record_candidate_row_page_cache_none, CandidatePageCache, CandidatePageCacheKey,
|
||||
CandidatePageSnapshot, CandidateResolvedPageCache, CandidateResolvedPageCacheKey,
|
||||
CandidateResolvedPageSnapshot, CandidateRowPageCache, CandidateRowPageCacheKey,
|
||||
};
|
||||
pub(crate) use dashboard_response::DashboardResponseCache;
|
||||
pub(crate) use direct_plan_bypass::DirectPlanBypassCache;
|
||||
|
||||
Reference in New Issue
Block a user