refactor: carry normalized client session affinity

This commit is contained in:
fawney19
2026-05-05 21:34:17 +08:00
parent ddf3fb6f63
commit 98421126f2
10 changed files with 141 additions and 13 deletions

View File

@@ -115,6 +115,7 @@ pub(crate) async fn maybe_build_local_same_format_provider_decision_payload_for_
request_origin: Some(crate::ai_serving::request_origin_from_parts(parts)),
original_request_body_json: Some(body_json),
original_request_body_base64: None,
client_session_affinity: input.client_session_affinity.as_ref(),
client_requested_stream: body_json
.get("stream")
.and_then(serde_json::Value::as_bool)

View File

@@ -6,10 +6,13 @@ use aether_ai_serving::{
provider_stream_event_api_format_for_provider_type as ai_provider_stream_event_api_format_for_provider_type,
AiExecutionReportContextParts, AiRequestOrigin,
};
use aether_scheduler_core::SchedulerRankingOutcome;
use aether_scheduler_core::{ClientSessionAffinity, SchedulerRankingOutcome};
use serde_json::{Map, Value};
use crate::ai_serving::{request_origin_from_headers, ExecutionRuntimeAuthContext, RequestOrigin};
use crate::client_session_affinity::{
client_session_affinity_report_context_value, CLIENT_SESSION_AFFINITY_REPORT_CONTEXT_FIELD,
};
use crate::orchestration::ExecutionAttemptIdentity;
pub(crate) struct LocalExecutionReportContextParts<'a> {
@@ -40,6 +43,7 @@ pub(crate) struct LocalExecutionReportContextParts<'a> {
pub(crate) request_origin: Option<RequestOrigin>,
pub(crate) original_request_body_json: Option<&'a Value>,
pub(crate) original_request_body_base64: Option<&'a str>,
pub(crate) client_session_affinity: Option<&'a ClientSessionAffinity>,
pub(crate) client_requested_stream: bool,
pub(crate) upstream_is_stream: bool,
pub(crate) has_envelope: bool,
@@ -61,6 +65,16 @@ pub(crate) fn build_local_execution_report_context(
parts.original_request_body_json,
parts.original_request_body_base64,
);
let mut extra_fields = parts.extra_fields;
if let Some(value) = parts
.client_session_affinity
.and_then(client_session_affinity_report_context_value)
{
extra_fields.insert(
CLIENT_SESSION_AFFINITY_REPORT_CONTEXT_FIELD.to_string(),
value,
);
}
build_ai_execution_report_context(AiExecutionReportContextParts {
auth_context: parts.auth_context,
@@ -98,7 +112,7 @@ pub(crate) fn build_local_execution_report_context(
upstream_is_stream: parts.upstream_is_stream,
has_envelope: parts.has_envelope,
needs_conversion: parts.needs_conversion,
extra_fields: parts.extra_fields,
extra_fields,
})
}
@@ -119,6 +133,7 @@ pub(crate) fn insert_provider_stream_event_api_format(
mod tests {
use std::collections::BTreeMap;
use aether_scheduler_core::ClientSessionAffinity;
use serde_json::{json, Map, Value};
use super::{
@@ -154,7 +169,7 @@ mod tests {
}
#[test]
fn local_execution_report_context_records_request_origin() {
fn local_execution_report_context_records_request_origin_and_session_affinity() {
let auth_context = ExecutionRuntimeAuthContext {
user_id: "user-1".to_string(),
api_key_id: "api-key-1".to_string(),
@@ -166,6 +181,10 @@ mod tests {
};
let original_headers = http::HeaderMap::new();
let provider_request_headers = BTreeMap::new();
let client_session_affinity = ClientSessionAffinity::new(
Some("codex".to_string()),
Some("account=account-1;session=session-1".to_string()),
);
let report_context =
build_local_execution_report_context(LocalExecutionReportContextParts {
@@ -199,6 +218,7 @@ mod tests {
}),
original_request_body_json: Some(&json!({"model": "gpt-5"})),
original_request_body_base64: None,
client_session_affinity: Some(&client_session_affinity),
client_requested_stream: false,
upstream_is_stream: false,
has_envelope: false,
@@ -214,5 +234,12 @@ mod tests {
report_context["user_agent"],
Value::String("Claude-Code/1.0".to_string())
);
assert_eq!(
report_context["client_session_affinity"],
json!({
"client_family": "codex",
"session_key": "account=account-1;session=session-1"
})
);
}
}

View File

@@ -97,6 +97,7 @@ pub(super) async fn maybe_build_local_gemini_files_decision_payload_for_candidat
request_origin: Some(crate::ai_serving::request_origin_from_parts(parts)),
original_request_body_json: Some(body_json),
original_request_body_base64: resolved.provider_request_body_base64.as_deref(),
client_session_affinity: input.client_session_affinity.as_ref(),
client_requested_stream: spec_metadata.require_streaming,
upstream_is_stream: spec_metadata.require_streaming,
has_envelope: false,

View File

@@ -92,6 +92,7 @@ pub(super) async fn maybe_build_local_openai_image_decision_payload_for_candidat
request_origin: Some(crate::ai_serving::request_origin_from_parts(parts)),
original_request_body_json: Some(body_json),
original_request_body_base64: body_base64,
client_session_affinity: input.client_session_affinity.as_ref(),
client_requested_stream: spec_metadata.require_streaming,
upstream_is_stream,
has_envelope: false,

View File

@@ -78,6 +78,7 @@ pub(super) async fn maybe_build_local_video_create_decision_payload_for_candidat
request_origin: Some(crate::ai_serving::request_origin_from_parts(parts)),
original_request_body_json: Some(body_json),
original_request_body_base64: None,
client_session_affinity: input.client_session_affinity.as_ref(),
client_requested_stream: false,
upstream_is_stream: false,
has_envelope: false,

View File

@@ -123,6 +123,7 @@ pub(super) async fn maybe_build_local_standard_decision_payload_for_candidate(
request_origin: Some(crate::ai_serving::request_origin_from_parts(parts)),
original_request_body_json: Some(body_json),
original_request_body_base64: None,
client_session_affinity: input.client_session_affinity.as_ref(),
client_requested_stream: body_json
.get("stream")
.and_then(serde_json::Value::as_bool)

View File

@@ -110,6 +110,7 @@ pub(crate) async fn maybe_build_local_openai_chat_decision_payload_for_candidate
request_origin: Some(crate::ai_serving::request_origin_from_parts(parts)),
original_request_body_json: Some(body_json),
original_request_body_base64: None,
client_session_affinity: input.client_session_affinity.as_ref(),
client_requested_stream: body_json
.get("stream")
.and_then(serde_json::Value::as_bool)

View File

@@ -108,6 +108,7 @@ pub(crate) async fn maybe_build_local_openai_responses_decision_payload_for_cand
request_origin: Some(crate::ai_serving::request_origin_from_parts(parts)),
original_request_body_json: Some(body_json),
original_request_body_base64: None,
client_session_affinity: input.client_session_affinity.as_ref(),
client_requested_stream: body_json
.get("stream")
.and_then(serde_json::Value::as_bool)