mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-12 22:20:19 +08:00
fix(ci): stabilize cross-platform workflow checks
This commit is contained in:
@@ -651,7 +651,7 @@ SELECT SHA2(UUID(), 256), usage.api_key_id, ?, COUNT(*),
|
||||
COALESCE(SUM(usage.cache_creation_input_tokens), 0),
|
||||
COALESCE(SUM(usage.cache_read_input_tokens), 0),
|
||||
COALESCE(SUM(usage.total_cost_usd), 0), MAX(api_keys.name), ?, ?
|
||||
FROM `usage` AS usage
|
||||
FROM `usage` AS `usage`
|
||||
LEFT JOIN api_keys ON api_keys.id = usage.api_key_id
|
||||
WHERE usage.created_at_unix_ms >= ? AND usage.created_at_unix_ms < ?
|
||||
AND usage.api_key_id IS NOT NULL AND usage.api_key_id <> ''
|
||||
@@ -736,7 +736,7 @@ SELECT SHA2(UUID(), 256), usage.user_id, ?, COUNT(*),
|
||||
COALESCE(SUM(usage.cache_creation_input_tokens), 0),
|
||||
COALESCE(SUM(usage.cache_read_input_tokens), 0),
|
||||
COALESCE(SUM(usage.total_cost_usd), 0), MAX(users.username), ?, ?
|
||||
FROM `usage` AS usage
|
||||
FROM `usage` AS `usage`
|
||||
LEFT JOIN users ON users.id = usage.user_id
|
||||
WHERE usage.created_at_unix_ms >= ? AND usage.created_at_unix_ms < ?
|
||||
AND usage.user_id IS NOT NULL AND usage.user_id <> ''
|
||||
|
||||
@@ -143,7 +143,7 @@ JOIN (
|
||||
MAX(CASE WHEN {SETTLED} THEN COALESCE(settlement.finalized_at, usage.finalized_at) END) AS settled_last_finalized_at_unix_secs,
|
||||
COALESCE(SUM(CASE WHEN usage.response_time_ms IS NOT NULL AND {AGGREGATABLE} THEN GREATEST(usage.response_time_ms, 0) ELSE 0 END), 0) AS response_time_sum_ms,
|
||||
COALESCE(SUM(CASE WHEN usage.response_time_ms IS NOT NULL AND {AGGREGATABLE} THEN 1 ELSE 0 END), 0) AS response_time_samples
|
||||
FROM `usage` AS usage
|
||||
FROM `usage` AS `usage`
|
||||
LEFT JOIN usage_settlement_snapshots AS settlement ON settlement.request_id = usage.request_id
|
||||
WHERE usage.created_at_unix_ms >= ? AND usage.created_at_unix_ms < ?
|
||||
) AS aggregated
|
||||
@@ -207,7 +207,7 @@ JOIN (
|
||||
COALESCE(SUM(CASE WHEN {SETTLED} THEN GREATEST(COALESCE(usage.cache_read_input_tokens, 0), 0) ELSE 0 END), 0) AS settled_cache_read_tokens,
|
||||
MIN(CASE WHEN {SETTLED} THEN COALESCE(settlement.finalized_at, usage.finalized_at) END) AS settled_first_finalized_at_unix_secs,
|
||||
MAX(CASE WHEN {SETTLED} THEN COALESCE(settlement.finalized_at, usage.finalized_at) END) AS settled_last_finalized_at_unix_secs
|
||||
FROM `usage` AS usage
|
||||
FROM `usage` AS `usage`
|
||||
LEFT JOIN usage_settlement_snapshots AS settlement ON settlement.request_id = usage.request_id
|
||||
WHERE usage.created_at_unix_ms >= ? AND usage.created_at_unix_ms < ?
|
||||
AND usage.user_id IS NOT NULL AND usage.user_id <> '' AND {AGGREGATABLE}
|
||||
@@ -266,7 +266,7 @@ JOIN (
|
||||
SELECT {select_dimensions},
|
||||
COALESCE(SUM(CASE WHEN usage.response_time_ms IS NOT NULL THEN GREATEST(usage.response_time_ms, 0) ELSE 0 END), 0) AS response_time_sum_ms,
|
||||
COALESCE(SUM(CASE WHEN usage.response_time_ms IS NOT NULL THEN 1 ELSE 0 END), 0) AS response_time_samples
|
||||
FROM `usage` AS usage
|
||||
FROM `usage` AS `usage`
|
||||
WHERE usage.created_at_unix_ms >= ? AND usage.created_at_unix_ms < ? AND {AGGREGATABLE}
|
||||
GROUP BY {group_by}
|
||||
) AS aggregated ON {join}
|
||||
@@ -391,7 +391,7 @@ JOIN (
|
||||
COALESCE(SUM(CASE WHEN {SETTLED} THEN GREATEST(COALESCE(usage.cache_read_input_tokens, 0), 0) ELSE 0 END), 0) AS settled_cache_read_tokens,
|
||||
MIN(CASE WHEN {SETTLED} THEN COALESCE(settlement.finalized_at, usage.finalized_at) END) AS settled_first_finalized_at_unix_secs,
|
||||
MAX(CASE WHEN {SETTLED} THEN COALESCE(settlement.finalized_at, usage.finalized_at) END) AS settled_last_finalized_at_unix_secs
|
||||
FROM `usage` AS usage
|
||||
FROM `usage` AS `usage`
|
||||
LEFT JOIN usage_settlement_snapshots AS settlement ON settlement.request_id = usage.request_id
|
||||
WHERE usage.created_at_unix_ms >= ? AND usage.created_at_unix_ms < ?
|
||||
) AS aggregated
|
||||
@@ -461,7 +461,7 @@ JOIN (
|
||||
COALESCE(SUM(CASE WHEN usage.response_time_ms IS NOT NULL THEN 1 ELSE 0 END), 0) AS response_time_samples,
|
||||
COALESCE(SUM({CACHE_5M}), 0) AS cache_creation_ephemeral_5m_tokens,
|
||||
COALESCE(SUM({CACHE_1H}), 0) AS cache_creation_ephemeral_1h_tokens
|
||||
FROM `usage` AS usage
|
||||
FROM `usage` AS `usage`
|
||||
WHERE usage.created_at_unix_ms >= ? AND usage.created_at_unix_ms < ?
|
||||
AND {AGGREGATABLE} AND usage.model IS NOT NULL AND usage.model <> ''
|
||||
GROUP BY usage.model
|
||||
@@ -503,7 +503,7 @@ JOIN (
|
||||
COALESCE(SUM(CASE WHEN {SETTLED} THEN GREATEST(COALESCE(usage.cache_read_input_tokens, 0), 0) ELSE 0 END), 0) AS settled_cache_read_tokens,
|
||||
MIN(CASE WHEN {SETTLED} THEN COALESCE(settlement.finalized_at, usage.finalized_at) END) AS settled_first_finalized_at_unix_secs,
|
||||
MAX(CASE WHEN {SETTLED} THEN COALESCE(settlement.finalized_at, usage.finalized_at) END) AS settled_last_finalized_at_unix_secs
|
||||
FROM `usage` AS usage
|
||||
FROM `usage` AS `usage`
|
||||
LEFT JOIN usage_settlement_snapshots AS settlement ON settlement.request_id = usage.request_id
|
||||
WHERE usage.created_at_unix_ms >= ? AND usage.created_at_unix_ms < ?
|
||||
AND usage.user_id IS NOT NULL AND usage.user_id <> '' AND {AGGREGATABLE}
|
||||
@@ -581,7 +581,7 @@ SELECT SHA2(UUID(), 256), usage.user_id,
|
||||
COALESCE(SUM(CASE WHEN ({SUCCESS}) = 1 AND usage.response_time_ms IS NOT NULL THEN GREATEST(usage.response_time_ms, 0) ELSE 0 END), 0),
|
||||
COALESCE(SUM(CASE WHEN ({SUCCESS}) = 1 AND usage.response_time_ms IS NOT NULL THEN 1 ELSE 0 END), 0),
|
||||
?, ?
|
||||
FROM `usage` AS usage
|
||||
FROM `usage` AS `usage`
|
||||
LEFT JOIN users ON users.id = usage.user_id
|
||||
LEFT JOIN usage_settlement_snapshots AS settlement ON settlement.request_id = usage.request_id
|
||||
WHERE usage.created_at_unix_ms >= ? AND usage.created_at_unix_ms < ?
|
||||
@@ -637,7 +637,7 @@ SELECT SHA2(UUID(), 256), ?, usage.model, usage.provider_name, COUNT(*),
|
||||
COALESCE(SUM(COALESCE(settlement.billing_total_cost_usd, usage.total_cost_usd, 0)), 0),
|
||||
COALESCE(SUM(CASE WHEN usage.response_time_ms IS NOT NULL THEN GREATEST(usage.response_time_ms, 0) ELSE 0 END), 0),
|
||||
COALESCE(SUM(CASE WHEN usage.response_time_ms IS NOT NULL THEN 1 ELSE 0 END), 0), ?, ?
|
||||
FROM `usage` AS usage
|
||||
FROM `usage` AS `usage`
|
||||
LEFT JOIN usage_settlement_snapshots AS settlement ON settlement.request_id = usage.request_id
|
||||
WHERE usage.created_at_unix_ms >= ? AND usage.created_at_unix_ms < ?
|
||||
AND usage.model IS NOT NULL AND usage.model <> '' AND {AGGREGATABLE}
|
||||
@@ -669,7 +669,7 @@ SELECT SHA2(UUID(), 256), usage.user_id, MAX(COALESCE(usage.username, users.user
|
||||
COALESCE(SUM(COALESCE(settlement.billing_total_cost_usd, usage.total_cost_usd, 0)), 0),
|
||||
COALESCE(SUM(CASE WHEN usage.response_time_ms IS NOT NULL THEN GREATEST(usage.response_time_ms, 0) ELSE 0 END), 0),
|
||||
COALESCE(SUM(CASE WHEN usage.response_time_ms IS NOT NULL THEN 1 ELSE 0 END), 0), ?, ?
|
||||
FROM `usage` AS usage
|
||||
FROM `usage` AS `usage`
|
||||
LEFT JOIN users ON users.id = usage.user_id
|
||||
LEFT JOIN usage_settlement_snapshots AS settlement ON settlement.request_id = usage.request_id
|
||||
WHERE usage.created_at_unix_ms >= ? AND usage.created_at_unix_ms < ?
|
||||
@@ -834,7 +834,7 @@ SELECT SHA2(UUID(), 256), {user_select}?, {dimension_select_sql}
|
||||
COALESCE(settlement.input_price_per_1m, usage.input_price_per_1m, 0)
|
||||
* GREATEST(COALESCE(usage.cache_read_input_tokens, 0), 0) / 1000000.0
|
||||
), 0), ?, ?
|
||||
FROM `usage` AS usage
|
||||
FROM `usage` AS `usage`
|
||||
LEFT JOIN usage_settlement_snapshots AS settlement ON settlement.request_id = usage.request_id
|
||||
{user_join}
|
||||
WHERE usage.created_at_unix_ms >= ? AND usage.created_at_unix_ms < ? {user_filter}
|
||||
|
||||
@@ -7,7 +7,7 @@ use tracing::info;
|
||||
// Generated by build.rs from schema/bootstrap/postgres.
|
||||
pub(crate) static EMPTY_DATABASE_SNAPSHOT_SQL: &str =
|
||||
include_str!(concat!(env!("OUT_DIR"), "/empty_database_snapshot.sql"));
|
||||
pub(crate) const EMPTY_DATABASE_SNAPSHOT_CUTOFF_VERSION: i64 = 20260720000000;
|
||||
pub(crate) const EMPTY_DATABASE_SNAPSHOT_CUTOFF_VERSION: i64 = 20260727000000;
|
||||
|
||||
const PUBLIC_BASE_TABLE_COUNT_SQL: &str = r#"
|
||||
SELECT COUNT(*)::BIGINT
|
||||
|
||||
@@ -536,6 +536,7 @@ const REQUEST_BODY_DETAIL_TABLES: &[&str] = &["usage_body_blobs"];
|
||||
#[cfg(all(feature = "postgres", feature = "sqlite"))]
|
||||
const LIFECYCLE_TABLES: &[&str] = &["_sqlx_migrations", "schema_backfills"];
|
||||
|
||||
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
|
||||
fn import_column_stores_timestamp(column_name: &str) -> bool {
|
||||
column_name.ends_with("_at")
|
||||
|| column_name.ends_with("_unix_secs")
|
||||
@@ -547,6 +548,7 @@ fn import_column_stores_timestamp(column_name: &str) -> bool {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
|
||||
fn import_timestamp_uses_millis(table_name: &str, column_name: &str) -> bool {
|
||||
if !column_name.ends_with("_unix_ms") {
|
||||
return false;
|
||||
@@ -562,6 +564,7 @@ fn import_timestamp_uses_millis(table_name: &str, column_name: &str) -> bool {
|
||||
!(relation_name == "usage" && column_name == "created_at_unix_ms")
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
|
||||
fn normalize_imported_integer_timestamp(
|
||||
driver_name: &str,
|
||||
table_name: &str,
|
||||
@@ -597,6 +600,7 @@ fn normalize_imported_integer_timestamp(
|
||||
Ok(Some(timestamp))
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
|
||||
fn parse_imported_datetime(value: &str) -> Option<chrono::DateTime<chrono::Utc>> {
|
||||
let value = value.trim();
|
||||
if let Ok(datetime) = chrono::DateTime::parse_from_rfc3339(value) {
|
||||
|
||||
@@ -476,9 +476,9 @@ async fn load_mysql_import_columns(
|
||||
let rows = sqlx::query(
|
||||
r#"
|
||||
SELECT
|
||||
COLUMN_NAME AS column_name,
|
||||
DATA_TYPE AS data_type,
|
||||
COLUMN_KEY AS column_key,
|
||||
CAST(COLUMN_NAME AS CHAR) AS column_name,
|
||||
CAST(DATA_TYPE AS CHAR) AS data_type,
|
||||
CAST(COLUMN_KEY AS CHAR) AS column_key,
|
||||
ORDINAL_POSITION AS ordinal_position
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = DATABASE()
|
||||
@@ -506,7 +506,7 @@ WHERE table_schema = DATABASE()
|
||||
.eq_ignore_ascii_case("PRI")
|
||||
{
|
||||
primary_key.insert(
|
||||
row.try_get::<i64, _>("ordinal_position").map_sql_err()?,
|
||||
row.try_get::<u32, _>("ordinal_position").map_sql_err()?,
|
||||
name,
|
||||
);
|
||||
}
|
||||
@@ -662,7 +662,9 @@ fn mysql_value_to_json(row: &sqlx::mysql::MySqlRow, index: usize) -> Result<Valu
|
||||
})
|
||||
}
|
||||
"DECIMAL" | "NEWDECIMAL" => Ok(Value::String(
|
||||
row.try_get::<String, _>(index).map_sql_err()?,
|
||||
row.try_get::<sqlx::types::BigDecimal, _>(index)
|
||||
.map_sql_err()?
|
||||
.to_string(),
|
||||
)),
|
||||
"VARCHAR" | "VAR_STRING" | "STRING" | "TEXT" | "TINYTEXT" | "MEDIUMTEXT" | "LONGTEXT"
|
||||
| "JSON" | "ENUM" | "SET" | "DATE" | "DATETIME" | "TIMESTAMP" | "TIME" => Ok(
|
||||
|
||||
@@ -488,6 +488,10 @@ fn normalize_postgres_import_value(
|
||||
if is_postgres_boolean_column(target_column) {
|
||||
return normalize_postgres_boolean_value(column_name, value);
|
||||
}
|
||||
if is_postgres_integer_column(target_column) && import_column_stores_timestamp(column_name) {
|
||||
return normalize_imported_integer_timestamp("postgres", table_name, column_name, value)
|
||||
.map(|timestamp| timestamp.map_or(Value::Null, |value| Value::Number(value.into())));
|
||||
}
|
||||
if is_postgres_timestamp_column(target_column) {
|
||||
return normalize_postgres_timestamp_value(table_name, column_name, value);
|
||||
}
|
||||
@@ -512,6 +516,13 @@ pub(super) fn is_postgres_timestamp_column(target_column: &PostgresImportColumn)
|
||||
) || matches!(target_column.udt_name.as_str(), "timestamptz" | "timestamp")
|
||||
}
|
||||
|
||||
fn is_postgres_integer_column(target_column: &PostgresImportColumn) -> bool {
|
||||
matches!(
|
||||
target_column.data_type.as_str(),
|
||||
"smallint" | "integer" | "bigint"
|
||||
) || matches!(target_column.udt_name.as_str(), "int2" | "int4" | "int8")
|
||||
}
|
||||
|
||||
fn is_postgres_json_column(target_column: &PostgresImportColumn) -> bool {
|
||||
matches!(target_column.data_type.as_str(), "json" | "jsonb")
|
||||
|| matches!(target_column.udt_name.as_str(), "json" | "jsonb")
|
||||
@@ -655,20 +666,6 @@ fn postgres_billing_table_name(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod billing_table_tests {
|
||||
use super::postgres_billing_table_name;
|
||||
|
||||
#[test]
|
||||
fn settlement_snapshot_import_uses_request_id_conflict_key() {
|
||||
assert_eq!(
|
||||
postgres_billing_table_name("usage_settlement_snapshots")
|
||||
.expect("settlement snapshot table should be supported"),
|
||||
("public.usage_settlement_snapshots", "request_id")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async fn import_postgres_wallet_row(
|
||||
tx: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
row: &ExportRow,
|
||||
@@ -721,3 +718,17 @@ fn postgres_wallet_table_name(
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod billing_table_tests {
|
||||
use super::postgres_billing_table_name;
|
||||
|
||||
#[test]
|
||||
fn settlement_snapshot_import_uses_request_id_conflict_key() {
|
||||
assert_eq!(
|
||||
postgres_billing_table_name("usage_settlement_snapshots")
|
||||
.expect("settlement snapshot table should be supported"),
|
||||
("public.usage_settlement_snapshots", "request_id")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,6 +290,23 @@ fn cross_driver_timestamp_normalization_preserves_usage_second_contract() {
|
||||
normalized["created_at_unix_ms"],
|
||||
json!("2023-11-14T22:13:20+00:00")
|
||||
);
|
||||
|
||||
let target_columns = BTreeMap::from([(
|
||||
"created_at_unix_ms".to_string(),
|
||||
postgres_column("bigint", "int8"),
|
||||
)]);
|
||||
let row = ExportRow {
|
||||
id: "usage-1".to_string(),
|
||||
payload: json!({ "created_at_unix_ms": "1970-01-01T00:00:01.234900Z" }),
|
||||
};
|
||||
let normalized = normalize_postgres_import_payload(
|
||||
"public.usage",
|
||||
ExportDomain::Usage,
|
||||
&row,
|
||||
&target_columns,
|
||||
)
|
||||
.expect("postgres integer usage timestamp should normalize");
|
||||
assert_eq!(normalized["created_at_unix_ms"], json!(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -409,6 +409,7 @@ fn empty_database_snapshot_covers_current_cutoff_versions() {
|
||||
20260718000000,
|
||||
20260718010000,
|
||||
20260720000000,
|
||||
20260727000000,
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -1023,6 +1024,7 @@ fn mysql_and_sqlite_migrations_include_enabled_incrementals() {
|
||||
20260725010000,
|
||||
20260725020000,
|
||||
20260725030000,
|
||||
20260727000000,
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -1055,6 +1057,7 @@ fn mysql_and_sqlite_migrations_include_enabled_incrementals() {
|
||||
20260725020000,
|
||||
20260725030000,
|
||||
20260725040000,
|
||||
20260727000000,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -664,7 +664,7 @@ mod tests {
|
||||
let provider_id = format!(
|
||||
"vertex-{}-{}",
|
||||
auth_type,
|
||||
api_format.replace(':', "-").replace('_', "-")
|
||||
api_format.replace([':', '_'], "-")
|
||||
);
|
||||
let mut row = sample_row(&provider_id, api_format, "vertex-model", 10);
|
||||
row.provider_type = "vertex_ai".to_string();
|
||||
|
||||
Reference in New Issue
Block a user