mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-01 17:00:21 +08:00
refactor: 移除独立 hub/proxy/executor/gateway crate,统一为 gateway tunnel 架构
- 删除 aether-hub、aether-proxy 独立项目及其 Dockerfile/配置 - 删除 crates/aether-executor 和 crates/aether-gateway 全部模块 - 新增 apps/ 目录作为应用入口 - 将 hub 概念重构为 gateway tunnel transport - 将 executor 重构为 execution runtime - 新增 tunnel.rs 合约定义和 testkit tunnel/execution_runtime 模块 - 更新 Python 服务层和测试适配新架构命名
This commit is contained in:
@@ -72,7 +72,7 @@ pub struct RedisStreamRunnerConfig {
|
||||
impl Default for RedisStreamRunnerConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
command_timeout_ms: Some(1_000),
|
||||
command_timeout_ms: Some(2_000),
|
||||
read_block_ms: Some(1_000),
|
||||
read_count: 32,
|
||||
}
|
||||
@@ -91,6 +91,16 @@ impl RedisStreamRunnerConfig {
|
||||
"redis stream read_block_ms must be positive".to_string(),
|
||||
));
|
||||
}
|
||||
if let (Some(command_timeout_ms), Some(read_block_ms)) =
|
||||
(self.command_timeout_ms, self.read_block_ms)
|
||||
{
|
||||
if command_timeout_ms <= read_block_ms {
|
||||
return Err(DataLayerError::InvalidConfiguration(
|
||||
"redis stream command_timeout_ms must be greater than read_block_ms"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
if self.read_count == 0 {
|
||||
return Err(DataLayerError::InvalidConfiguration(
|
||||
"redis stream read_count must be positive".to_string(),
|
||||
@@ -564,6 +574,13 @@ mod tests {
|
||||
}
|
||||
.validate()
|
||||
.is_err());
|
||||
assert!(RedisStreamRunnerConfig {
|
||||
command_timeout_ms: Some(1_000),
|
||||
read_block_ms: Some(1_000),
|
||||
..RedisStreamRunnerConfig::default()
|
||||
}
|
||||
.validate()
|
||||
.is_err());
|
||||
assert!(RedisStreamRunnerConfig {
|
||||
read_count: 0,
|
||||
..RedisStreamRunnerConfig::default()
|
||||
|
||||
@@ -178,7 +178,7 @@ impl ProxyNodeWriteRepository for InMemoryProxyNodeRepository {
|
||||
};
|
||||
let event_detail = mutation.detail.clone().unwrap_or_else(|| {
|
||||
format!(
|
||||
"[hub_node_status] conn_count={}",
|
||||
"[tunnel_node_status] conn_count={}",
|
||||
i32::max(mutation.conn_count, 0)
|
||||
)
|
||||
});
|
||||
@@ -318,7 +318,7 @@ mod tests {
|
||||
assert_eq!(stale_events[0].event_type, "disconnected");
|
||||
assert_eq!(
|
||||
stale_events[0].detail.as_deref(),
|
||||
Some("[stale_ignored] [hub_node_status] conn_count=0")
|
||||
Some("[stale_ignored] [tunnel_node_status] conn_count=0")
|
||||
);
|
||||
|
||||
let updated = repository
|
||||
@@ -344,7 +344,7 @@ mod tests {
|
||||
assert_eq!(events[0].created_at_unix_secs, Some(1_800_000_000));
|
||||
assert_eq!(
|
||||
events[0].detail.as_deref(),
|
||||
Some("[hub_node_status] conn_count=0")
|
||||
Some("[tunnel_node_status] conn_count=0")
|
||||
);
|
||||
|
||||
let found = repository
|
||||
|
||||
@@ -278,7 +278,7 @@ impl ProxyNodeWriteRepository for SqlxProxyNodeRepository {
|
||||
};
|
||||
let event_detail = mutation.detail.clone().unwrap_or_else(|| {
|
||||
format!(
|
||||
"[hub_node_status] conn_count={}",
|
||||
"[tunnel_node_status] conn_count={}",
|
||||
i32::max(mutation.conn_count, 0)
|
||||
)
|
||||
});
|
||||
|
||||
@@ -293,6 +293,33 @@ impl UsageWriteRepository for InMemoryUsageReadRepository {
|
||||
first_byte_time_ms: usage.first_byte_time_ms,
|
||||
status: usage.status,
|
||||
billing_status: usage.billing_status,
|
||||
request_headers: usage
|
||||
.request_headers
|
||||
.or_else(|| existing.and_then(|existing| existing.request_headers.clone())),
|
||||
request_body: usage
|
||||
.request_body
|
||||
.or_else(|| existing.and_then(|existing| existing.request_body.clone())),
|
||||
provider_request_headers: usage.provider_request_headers.or_else(|| {
|
||||
existing.and_then(|existing| existing.provider_request_headers.clone())
|
||||
}),
|
||||
provider_request_body: usage
|
||||
.provider_request_body
|
||||
.or_else(|| existing.and_then(|existing| existing.provider_request_body.clone())),
|
||||
response_headers: usage
|
||||
.response_headers
|
||||
.or_else(|| existing.and_then(|existing| existing.response_headers.clone())),
|
||||
response_body: usage
|
||||
.response_body
|
||||
.or_else(|| existing.and_then(|existing| existing.response_body.clone())),
|
||||
client_response_headers: usage
|
||||
.client_response_headers
|
||||
.or_else(|| existing.and_then(|existing| existing.client_response_headers.clone())),
|
||||
client_response_body: usage
|
||||
.client_response_body
|
||||
.or_else(|| existing.and_then(|existing| existing.client_response_body.clone())),
|
||||
request_metadata: usage
|
||||
.request_metadata
|
||||
.or_else(|| existing.and_then(|existing| existing.request_metadata.clone())),
|
||||
created_at_unix_secs,
|
||||
updated_at_unix_secs: usage.updated_at_unix_secs,
|
||||
finalized_at_unix_secs: usage.finalized_at_unix_secs,
|
||||
|
||||
@@ -50,6 +50,15 @@ SELECT
|
||||
first_byte_time_ms,
|
||||
status,
|
||||
billing_status,
|
||||
request_headers,
|
||||
request_body,
|
||||
provider_request_headers,
|
||||
provider_request_body,
|
||||
response_headers,
|
||||
response_body,
|
||||
client_response_headers,
|
||||
client_response_body,
|
||||
request_metadata,
|
||||
CAST(EXTRACT(EPOCH FROM created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM COALESCE(finalized_at, created_at)) AS BIGINT) AS updated_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM finalized_at) AS BIGINT) AS finalized_at_unix_secs
|
||||
@@ -98,6 +107,15 @@ SELECT
|
||||
first_byte_time_ms,
|
||||
status,
|
||||
billing_status,
|
||||
request_headers,
|
||||
request_body,
|
||||
provider_request_headers,
|
||||
provider_request_body,
|
||||
response_headers,
|
||||
response_body,
|
||||
client_response_headers,
|
||||
client_response_body,
|
||||
request_metadata,
|
||||
CAST(EXTRACT(EPOCH FROM created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM COALESCE(finalized_at, created_at)) AS BIGINT) AS updated_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM finalized_at) AS BIGINT) AS finalized_at_unix_secs
|
||||
@@ -176,6 +194,15 @@ SELECT
|
||||
first_byte_time_ms,
|
||||
status,
|
||||
billing_status,
|
||||
NULL::jsonb AS request_headers,
|
||||
NULL::jsonb AS request_body,
|
||||
NULL::jsonb AS provider_request_headers,
|
||||
NULL::jsonb AS provider_request_body,
|
||||
NULL::jsonb AS response_headers,
|
||||
NULL::jsonb AS response_body,
|
||||
NULL::jsonb AS client_response_headers,
|
||||
NULL::jsonb AS client_response_body,
|
||||
NULL::jsonb AS request_metadata,
|
||||
CAST(EXTRACT(EPOCH FROM created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM COALESCE(finalized_at, created_at)) AS BIGINT) AS updated_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM finalized_at) AS BIGINT) AS finalized_at_unix_secs
|
||||
@@ -222,6 +249,15 @@ SELECT
|
||||
first_byte_time_ms,
|
||||
status,
|
||||
billing_status,
|
||||
NULL::jsonb AS request_headers,
|
||||
NULL::jsonb AS request_body,
|
||||
NULL::jsonb AS provider_request_headers,
|
||||
NULL::jsonb AS provider_request_body,
|
||||
NULL::jsonb AS response_headers,
|
||||
NULL::jsonb AS response_body,
|
||||
NULL::jsonb AS client_response_headers,
|
||||
NULL::jsonb AS client_response_body,
|
||||
NULL::jsonb AS request_metadata,
|
||||
CAST(EXTRACT(EPOCH FROM created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM COALESCE(finalized_at, created_at)) AS BIGINT) AS updated_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM finalized_at) AS BIGINT) AS finalized_at_unix_secs
|
||||
@@ -326,11 +362,12 @@ INSERT INTO "usage" (
|
||||
$44,
|
||||
$45,
|
||||
$46,
|
||||
$47,
|
||||
CASE
|
||||
WHEN $47 IS NULL THEN NULL
|
||||
ELSE TO_TIMESTAMP($47::double precision)
|
||||
WHEN $48 IS NULL THEN NULL
|
||||
ELSE TO_TIMESTAMP($48::double precision)
|
||||
END,
|
||||
COALESCE(TO_TIMESTAMP($48::double precision), NOW())
|
||||
COALESCE(TO_TIMESTAMP($49::double precision), NOW())
|
||||
)
|
||||
ON CONFLICT (request_id)
|
||||
DO UPDATE SET
|
||||
@@ -419,6 +456,15 @@ RETURNING
|
||||
first_byte_time_ms,
|
||||
status,
|
||||
billing_status,
|
||||
request_headers,
|
||||
request_body,
|
||||
provider_request_headers,
|
||||
provider_request_body,
|
||||
response_headers,
|
||||
response_body,
|
||||
client_response_headers,
|
||||
client_response_body,
|
||||
request_metadata,
|
||||
CAST(EXTRACT(EPOCH FROM created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM COALESCE(finalized_at, created_at)) AS BIGINT) AS updated_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM finalized_at) AS BIGINT) AS finalized_at_unix_secs
|
||||
@@ -760,6 +806,15 @@ fn map_usage_row(row: &sqlx::postgres::PgRow) -> Result<StoredRequestUsageAudit,
|
||||
usage.cache_creation_cost_usd = row.try_get::<f64, _>("cache_creation_cost_usd")?;
|
||||
usage.cache_read_cost_usd = row.try_get::<f64, _>("cache_read_cost_usd")?;
|
||||
usage.output_price_per_1m = row.try_get("output_price_per_1m")?;
|
||||
usage.request_headers = row.try_get("request_headers")?;
|
||||
usage.request_body = row.try_get("request_body")?;
|
||||
usage.provider_request_headers = row.try_get("provider_request_headers")?;
|
||||
usage.provider_request_body = row.try_get("provider_request_body")?;
|
||||
usage.response_headers = row.try_get("response_headers")?;
|
||||
usage.response_body = row.try_get("response_body")?;
|
||||
usage.client_response_headers = row.try_get("client_response_headers")?;
|
||||
usage.client_response_body = row.try_get("client_response_body")?;
|
||||
usage.request_metadata = row.try_get("request_metadata")?;
|
||||
Ok(usage)
|
||||
}
|
||||
|
||||
@@ -891,4 +946,11 @@ mod tests {
|
||||
fn usage_sql_supports_recent_usage_audits_query() {
|
||||
assert!(super::LIST_RECENT_USAGE_AUDITS_PREFIX.contains("FROM \"usage\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn usage_sql_insert_values_aligns_request_metadata_and_timestamps() {
|
||||
assert!(super::UPSERT_SQL.contains("\n $46,\n $47,\n CASE"));
|
||||
assert!(super::UPSERT_SQL.contains("WHEN $48 IS NULL THEN NULL"));
|
||||
assert!(super::UPSERT_SQL.contains("TO_TIMESTAMP($49::double precision)"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,24 @@ pub struct StoredRequestUsageAudit {
|
||||
pub first_byte_time_ms: Option<u64>,
|
||||
pub status: String,
|
||||
pub billing_status: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub request_headers: Option<Value>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub request_body: Option<Value>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub provider_request_headers: Option<Value>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub provider_request_body: Option<Value>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub response_headers: Option<Value>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub response_body: Option<Value>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub client_response_headers: Option<Value>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub client_response_body: Option<Value>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub request_metadata: Option<Value>,
|
||||
pub created_at_unix_secs: u64,
|
||||
pub updated_at_unix_secs: u64,
|
||||
pub finalized_at_unix_secs: Option<u64>,
|
||||
@@ -161,6 +179,15 @@ impl StoredRequestUsageAudit {
|
||||
first_byte_time_ms: parse_optional_u64(first_byte_time_ms, "usage.first_byte_time_ms")?,
|
||||
status,
|
||||
billing_status,
|
||||
request_headers: None,
|
||||
request_body: None,
|
||||
provider_request_headers: None,
|
||||
provider_request_body: None,
|
||||
response_headers: None,
|
||||
response_body: None,
|
||||
client_response_headers: None,
|
||||
client_response_body: None,
|
||||
request_metadata: None,
|
||||
created_at_unix_secs: parse_timestamp(
|
||||
created_at_unix_secs,
|
||||
"usage.created_at_unix_secs",
|
||||
|
||||
Reference in New Issue
Block a user