mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-01 17:00:21 +08:00
fix(data): repair request candidate epoch created_at (#343)
Co-authored-by: fawney19 <elky0401@gmail.com>
This commit is contained in:
@@ -219,7 +219,14 @@ VALUES (
|
||||
$19,
|
||||
$20,
|
||||
$21,
|
||||
TO_TIMESTAMP(COALESCE($22, 0) / 1000.0),
|
||||
COALESCE(
|
||||
CASE
|
||||
WHEN $22 IS NOT NULL AND $22 > 1000.0 THEN TO_TIMESTAMP($22 / 1000.0)
|
||||
END,
|
||||
TO_TIMESTAMP($23 / 1000.0),
|
||||
TO_TIMESTAMP($24 / 1000.0),
|
||||
NOW()
|
||||
),
|
||||
TO_TIMESTAMP($23 / 1000.0),
|
||||
TO_TIMESTAMP($24 / 1000.0)
|
||||
)
|
||||
@@ -249,6 +256,11 @@ DO UPDATE SET
|
||||
ELSE EXCLUDED.extra_data
|
||||
END,
|
||||
required_capabilities = COALESCE(EXCLUDED.required_capabilities, request_candidates.required_capabilities),
|
||||
created_at = CASE
|
||||
WHEN request_candidates.created_at <= TO_TIMESTAMP(1)
|
||||
THEN EXCLUDED.created_at
|
||||
ELSE request_candidates.created_at
|
||||
END,
|
||||
started_at = COALESCE(EXCLUDED.started_at, request_candidates.started_at),
|
||||
finished_at = COALESCE(EXCLUDED.finished_at, request_candidates.finished_at)
|
||||
RETURNING
|
||||
@@ -740,9 +752,21 @@ fn to_i32_u64(value: u64) -> Result<i32, DataLayerError> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::SqlxRequestCandidateReadRepository;
|
||||
use super::{SqlxRequestCandidateReadRepository, UPSERT_SQL};
|
||||
use crate::postgres::{PostgresPoolConfig, PostgresPoolFactory};
|
||||
|
||||
#[test]
|
||||
fn upsert_sql_does_not_default_missing_or_epoch_created_at_to_epoch() {
|
||||
assert!(!UPSERT_SQL.contains("COALESCE($22, 0)"));
|
||||
assert!(UPSERT_SQL.contains("WHEN $22 IS NOT NULL AND $22 > 1000.0"));
|
||||
assert!(UPSERT_SQL.contains("TO_TIMESTAMP($22 / 1000.0)"));
|
||||
assert!(UPSERT_SQL.contains("TO_TIMESTAMP($23 / 1000.0)"));
|
||||
assert!(UPSERT_SQL.contains("TO_TIMESTAMP($24 / 1000.0)"));
|
||||
assert!(UPSERT_SQL.contains("NOW()"));
|
||||
assert!(UPSERT_SQL.contains("request_candidates.created_at <= TO_TIMESTAMP(1)"));
|
||||
assert!(UPSERT_SQL.contains("THEN EXCLUDED.created_at"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn repository_constructs_from_lazy_pool() {
|
||||
let factory = PostgresPoolFactory::new(PostgresPoolConfig {
|
||||
|
||||
@@ -156,7 +156,7 @@ mod tests {
|
||||
"claude",
|
||||
));
|
||||
assert!(!provider_matches_allowed_value(
|
||||
"anthropic",
|
||||
"vendor-x",
|
||||
"provider-1",
|
||||
"Other",
|
||||
"claude",
|
||||
@@ -164,11 +164,11 @@ mod tests {
|
||||
assert!(!provider_matches_allowed_value(
|
||||
"claude",
|
||||
"provider-1",
|
||||
"Anthropic",
|
||||
"OtherVendor",
|
||||
"custom",
|
||||
));
|
||||
assert!(!provider_matches_allowed_value(
|
||||
"anthropic:messages",
|
||||
"provider-1:extra",
|
||||
"provider-1",
|
||||
"Other",
|
||||
"claude",
|
||||
@@ -201,38 +201,22 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn api_format_allowed_value_rejects_retired_aliases() {
|
||||
assert!(!api_format_matches_allowed_value(
|
||||
"anthropic:messages",
|
||||
"claude:messages"
|
||||
));
|
||||
assert!(!api_format_matches_allowed_value(
|
||||
"claude:chat",
|
||||
"claude:messages"
|
||||
));
|
||||
assert!(!api_format_matches_allowed_value(
|
||||
"claude:cli",
|
||||
"claude:messages"
|
||||
));
|
||||
assert!(!api_format_matches_allowed_value(
|
||||
"openai:cli",
|
||||
"openai:responses"
|
||||
));
|
||||
assert!(!api_format_matches_allowed_value(
|
||||
"openai:compact",
|
||||
"openai:responses:compact"
|
||||
));
|
||||
assert!(!api_format_matches_allowed_value(
|
||||
"gemini:chat",
|
||||
"gemini:generate_content"
|
||||
));
|
||||
fn api_format_allowed_value_matches_current_signatures_only() {
|
||||
assert!(api_format_matches_allowed_value(
|
||||
"CLAUDE:MESSAGES",
|
||||
"claude:messages"
|
||||
));
|
||||
assert!(api_format_matches_allowed_value(
|
||||
"openai:responses",
|
||||
"openai:responses"
|
||||
));
|
||||
assert!(!api_format_matches_allowed_value(
|
||||
"openai:responses",
|
||||
"claude:messages"
|
||||
));
|
||||
assert!(!api_format_matches_allowed_value(
|
||||
"claude:messages:extra",
|
||||
"claude:messages"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,6 +438,10 @@ pub fn build_report_request_candidate_status_record(
|
||||
let finished_at_unix_ms = finished_at_unix_ms
|
||||
.or(slot.finished_at_unix_ms)
|
||||
.or_else(|| is_terminal_candidate_status(status).then_some(terminal_unix_secs));
|
||||
let created_at_unix_ms = non_epoch_unix_ms(slot.created_at_unix_ms)
|
||||
.or_else(|| started_at_unix_ms.and_then(non_epoch_unix_ms))
|
||||
.or_else(|| finished_at_unix_ms.and_then(non_epoch_unix_ms))
|
||||
.unwrap_or(terminal_unix_secs);
|
||||
|
||||
UpsertRequestCandidateRecord {
|
||||
id: slot.id,
|
||||
@@ -461,12 +465,16 @@ pub fn build_report_request_candidate_status_record(
|
||||
concurrent_requests: None,
|
||||
extra_data: slot.extra_data,
|
||||
required_capabilities: None,
|
||||
created_at_unix_ms: Some(slot.created_at_unix_ms),
|
||||
created_at_unix_ms: Some(created_at_unix_ms),
|
||||
started_at_unix_ms,
|
||||
finished_at_unix_ms,
|
||||
}
|
||||
}
|
||||
|
||||
fn non_epoch_unix_ms(value: u64) -> Option<u64> {
|
||||
(value > 1000).then_some(value)
|
||||
}
|
||||
|
||||
pub fn finalize_execution_request_candidate_report_context(
|
||||
report_context: Value,
|
||||
candidate_id: &str,
|
||||
@@ -1072,7 +1080,43 @@ mod tests {
|
||||
|
||||
assert_eq!(record.started_at_unix_ms, Some(123));
|
||||
assert_eq!(record.finished_at_unix_ms, Some(123));
|
||||
assert_eq!(record.created_at_unix_ms, Some(10));
|
||||
assert_eq!(record.created_at_unix_ms, Some(123));
|
||||
assert_eq!(record.status, RequestCandidateStatus::Success);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn report_request_candidate_status_record_repairs_epoch_created_at() {
|
||||
let record =
|
||||
build_report_request_candidate_status_record(ReportRequestCandidateStatusRecordInput {
|
||||
slot: SchedulerResolvedReportRequestCandidateSlot {
|
||||
id: "cand-epoch".to_string(),
|
||||
request_id: "req-epoch".to_string(),
|
||||
user_id: None,
|
||||
api_key_id: None,
|
||||
candidate_index: 0,
|
||||
retry_index: 0,
|
||||
provider_id: Some("provider-1".to_string()),
|
||||
endpoint_id: Some("endpoint-1".to_string()),
|
||||
key_id: Some("key-1".to_string()),
|
||||
extra_data: None,
|
||||
created_at_unix_ms: 0,
|
||||
started_at_unix_ms: None,
|
||||
finished_at_unix_ms: None,
|
||||
},
|
||||
status_update: SchedulerRequestCandidateStatusUpdate {
|
||||
status: RequestCandidateStatus::Success,
|
||||
status_code: Some(200),
|
||||
error_type: None,
|
||||
error_message: None,
|
||||
latency_ms: Some(12),
|
||||
started_at_unix_ms: Some(2_000),
|
||||
finished_at_unix_ms: Some(3_000),
|
||||
},
|
||||
now_unix_ms: 4_000,
|
||||
});
|
||||
|
||||
assert_eq!(record.created_at_unix_ms, Some(2_000));
|
||||
assert_eq!(record.started_at_unix_ms, Some(2_000));
|
||||
assert_eq!(record.finished_at_unix_ms, Some(3_000));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user