Files
codex-proxy-rs/backend/crates/gateway-store/tests/postgres/execution.rs
T
zyycnandCodex a6bac4601e chore(release): prepare v3.0.0
Refresh verified dependencies, harden CI test credentials, and align release builders with the current supported image.

Co-authored-by: Codex <noreply@openai.com>
2026-07-25 01:54:18 +08:00

341 lines
12 KiB
Rust

use chrono::{Duration, Utc};
use gateway_core::accounting::{CalculatedCost, CostEstimate, Usage};
use gateway_core::engine::{
ExecutionOutcome, ExecutionStore, ModelRequestFinalization as CoreModelRequestFinalization,
ModelRequestId, ModelRequestTimings as CoreModelRequestTimings, UpstreamSendState,
};
use gateway_store::postgres::{ModelRequestRepository, NewModelRequest, PgExecutionStore};
use super::TestDatabase;
#[test]
fn postgres_execution_adapter_implements_core_port() {
fn assert_port<T: ExecutionStore>() {}
assert_port::<PgExecutionStore>();
}
#[test]
fn model_request_rejects_mismatched_client_key_live_id() {
let started_at = Utc::now();
let request = NewModelRequest {
id: "request-1".to_owned(),
client_api_key_id: Some("key-live".to_owned()),
client_api_key_ref: "key-history".to_owned(),
config_revision: 1,
protocol: "openai".to_owned(),
operation: "responses".to_owned(),
endpoint: "/v1/responses".to_owned(),
client_transport: "http_sse".to_owned(),
requested_model_id: "coding".to_owned(),
client_ip: None,
user_agent: None,
reasoning_effort: None,
reasoning_preset: None,
request_kind: None,
subagent_kind: None,
compact: false,
image_generation_requested: false,
started_at,
deadline_at: started_at + Duration::seconds(30),
};
assert!(request.validate().is_err());
}
#[tokio::test]
async fn downstream_commit_should_atomically_record_http_status_once() {
let Some(database) = TestDatabase::create("execution_commit_status").await else {
return;
};
seed_running_request(&database.pool, "req_commit_status")
.await
.expect("seed model request");
let repository = PgExecutionStore::new(database.pool.clone());
let committed = ModelRequestRepository::mark_downstream_committed(
&repository,
"req_commit_status",
Utc::now(),
Some(200),
)
.await
.expect("commit downstream");
let overwritten = repository
.record_client_status_code("req_commit_status", 500)
.await
.expect("reject status overwrite without store failure");
let (committed_at, status): (Option<chrono::DateTime<Utc>>, Option<i32>) = sqlx::query_as(
"select downstream_committed_at, client_status_code
from model_requests where id = 'req_commit_status'",
)
.fetch_one(&database.pool)
.await
.expect("load committed request");
assert!(committed);
assert!(!overwritten);
assert!(committed_at.is_some());
assert_eq!(status, Some(200));
database.close().await;
}
#[tokio::test]
async fn terminal_failure_should_accept_exactly_one_client_status_backfill() {
let Some(database) = TestDatabase::create("execution_terminal_status").await else {
return;
};
seed_running_request(&database.pool, "req_terminal_status")
.await
.expect("seed model request");
sqlx::query(
"update model_requests
set outcome = 'failed', completed_at = now()
where id = 'req_terminal_status'",
)
.execute(&database.pool)
.await
.expect("finalize model request");
let repository = PgExecutionStore::new(database.pool.clone());
let recorded = repository
.record_client_status_code("req_terminal_status", 429)
.await
.expect("record terminal client status");
let overwritten = repository
.record_client_status_code("req_terminal_status", 500)
.await
.expect("reject terminal status overwrite without store failure");
let status: Option<i32> = sqlx::query_scalar(
"select client_status_code from model_requests where id = 'req_terminal_status'",
)
.fetch_one(&database.pool)
.await
.expect("load terminal client status");
assert!(recorded);
assert!(!overwritten);
assert_eq!(status, Some(429));
database.close().await;
}
#[tokio::test]
async fn core_adapter_should_persist_calculated_cost_exactly() {
let Some(database) = TestDatabase::create("execution_calculated_cost").await else {
return;
};
seed_running_request(&database.pool, "req_calculated_cost")
.await
.expect("seed model request");
sqlx::query(
"update model_requests
set provider_kind = 'xai', provider_account_ref = 'acct_xai',
upstream_model_id = 'grok-4.5', upstream_transport = 'http_sse', attempt_count = 1
where id = 'req_calculated_cost'",
)
.execute(&database.pool)
.await
.expect("seed model request attempt");
let repository = PgExecutionStore::new(database.pool.clone());
let mut finalization = successful_core_finalization("req_calculated_cost");
finalization.websocket_pool = Some("reuse".to_owned());
finalization.cost = CalculatedCost::from_usd_ticks(12_345)
.expect("calculated cost")
.into_estimate();
ExecutionStore::finalize_model_request(&repository, finalization)
.await
.expect("persist calculated cost");
let persisted: (String, String, String, String, String, String) = sqlx::query_as(
"select cost_source, cost_amount::text, cost_currency, upstream_transport, http_version,
websocket_pool
from model_requests where id = 'req_calculated_cost'",
)
.fetch_one(&database.pool)
.await
.expect("load calculated cost");
assert_eq!(
persisted,
(
"calculated".to_owned(),
"0.0000012345".to_owned(),
"USD".to_owned(),
"websocket".to_owned(),
"HTTP/2".to_owned(),
"reuse".to_owned(),
)
);
database.close().await;
}
#[tokio::test]
async fn core_adapter_should_persist_image_result_and_new_websocket_pool() {
let Some(database) = TestDatabase::create("execution_image_usage").await else {
return;
};
seed_running_request(&database.pool, "req_image_usage")
.await
.expect("seed image request");
sqlx::query(
"update model_requests
set image_generation_requested = true, provider_kind = 'openai',
provider_account_ref = 'acct_openai', upstream_model_id = 'gpt-image',
upstream_transport = 'websocket', attempt_count = 1
where id = 'req_image_usage'",
)
.execute(&database.pool)
.await
.expect("seed image attempt");
let repository = PgExecutionStore::new(database.pool.clone());
let mut usage = Usage::new();
usage.image_input_tokens = Some(31);
usage.image_output_tokens = Some(9);
let mut finalization = successful_core_finalization("req_image_usage");
finalization.usage = usage;
finalization.image_generation_succeeded = Some(true);
finalization.websocket_pool = Some("new".to_owned());
ExecutionStore::finalize_model_request(&repository, finalization)
.await
.expect("persist image usage");
let persisted: (bool, Option<i64>, Option<i64>, Option<bool>, Option<String>) = sqlx::query_as(
"select image_generation_requested, image_input_tokens, image_output_tokens,
image_generation_succeeded, websocket_pool
from model_requests where id = 'req_image_usage'",
)
.fetch_one(&database.pool)
.await
.expect("load image usage");
assert_eq!(
persisted,
(true, Some(31), Some(9), Some(true), Some("new".to_owned()))
);
database.close().await;
}
#[tokio::test]
async fn expired_image_request_should_be_recovered_as_failed() {
let Some(database) = TestDatabase::create("execution_expired_image").await else {
return;
};
seed_running_request(&database.pool, "req_expired_image")
.await
.expect("seed image request");
sqlx::query(
"update model_requests
set image_generation_requested = true,
started_at = now() - interval '2 seconds',
deadline_at = now() - interval '1 second'
where id = 'req_expired_image'",
)
.execute(&database.pool)
.await
.expect("expire image request");
let repository = PgExecutionStore::new(database.pool.clone());
repository
.recover_expired_model_requests(Utc::now())
.await
.expect("recover expired image request");
let persisted: (String, Option<bool>) = sqlx::query_as(
"select outcome, image_generation_succeeded
from model_requests where id = 'req_expired_image'",
)
.fetch_one(&database.pool)
.await
.expect("load recovered image request");
assert_eq!(persisted, ("incomplete".to_owned(), Some(false)));
database.close().await;
}
fn successful_core_finalization(id: &str) -> CoreModelRequestFinalization {
CoreModelRequestFinalization {
request_id: ModelRequestId::new(id).expect("request id"),
outcome: ExecutionOutcome::Succeeded,
send_state: UpstreamSendState::Sent,
attempt_count: 1,
downstream_committed_at: None,
client_status_code: Some(200),
client_response_id: None,
upstream_status_code: Some(200),
upstream_request_id: None,
upstream_response_id: None,
upstream_transport: Some("websocket".to_owned()),
http_version: Some("HTTP/2".to_owned()),
websocket_pool: None,
provider_metadata_json: None,
error: None,
provider_error_code: None,
retry_after_ms: None,
usage: Usage::new(),
image_generation_succeeded: None,
cost: CostEstimate::unavailable(),
timings: CoreModelRequestTimings::default(),
completed_at: std::time::SystemTime::now(),
}
}
#[tokio::test]
async fn core_adapter_should_persist_only_object_provider_observation() {
let Some(database) = TestDatabase::create("execution_provider_observation").await else {
return;
};
seed_running_request(&database.pool, "req_provider_observation")
.await
.expect("seed model request");
let store = PgExecutionStore::new(database.pool.clone());
let mut finalization = successful_core_finalization("req_provider_observation");
finalization.provider_metadata_json = Some("{\"effectiveModel\":\"gpt-test\"}".to_owned());
ExecutionStore::finalize_model_request(&store, finalization)
.await
.expect("persist provider observation");
let persisted: serde_json::Value = sqlx::query_scalar(
"select provider_observation_json from model_requests where id = 'req_provider_observation'",
)
.fetch_one(&database.pool)
.await
.expect("load provider observation");
assert_eq!(persisted["effectiveModel"], "gpt-test");
database.close().await;
}
#[tokio::test]
async fn core_adapter_should_reject_non_object_provider_observation() {
let Some(database) = TestDatabase::create("execution_invalid_provider_observation").await
else {
return;
};
seed_running_request(&database.pool, "req_invalid_provider_observation")
.await
.expect("seed model request");
let store = PgExecutionStore::new(database.pool.clone());
let mut finalization = successful_core_finalization("req_invalid_provider_observation");
finalization.provider_metadata_json = Some("[]".to_owned());
assert!(
ExecutionStore::finalize_model_request(&store, finalization)
.await
.is_err()
);
database.close().await;
}
async fn seed_running_request(pool: &sqlx::PgPool, id: &str) -> Result<(), sqlx::Error> {
sqlx::query(
"insert into model_requests (
id, client_api_key_ref, config_revision, protocol, operation, endpoint,
client_transport, requested_model_id, provider_kind, provider_account_ref, cost_source,
started_at, deadline_at
) values ($1, 'key_status', 1, 'openai_responses', 'generate', '/v1/responses',
'http_json', 'status-model', 'openai', 'acct_status', 'unavailable', now(), now() + interval '1 minute')",
)
.bind(id)
.execute(pool)
.await?;
Ok(())
}