mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-08 10:27:46 +08:00
Fix/api key concurrency runtime miss (#309)
* test(cli): 覆盖 API key 并发等待与超时路径 * feat(scheduler): API key 并发饱和时等待可用槽位 * fix(proxy): 区分 API key 并发受限与真正的 runtime miss * fix(outcome): runtime miss 仅归因真实执行候选 * feat(api-keys): 统一 concurrent_limit 默认值与校验辅助 * feat(admin): 独立 Key 接口支持 concurrent_limit * feat(admin): 用户 API Key 路由支持 concurrent_limit * feat(public): 自助 API Key 路由支持 concurrent_limit * feat(import): 导入与存储层持久化 concurrent_limit * feat(frontend): 同步 API Key concurrent_limit 类型定义 * feat(frontend): 独立 Key 表单支持 concurrent_limit * feat(frontend): 管理员用户 API Key 表单支持 concurrent_limit * feat(frontend): 自助 API Key 页面支持 concurrent_limit * chore(fmt): 统一 runtime 归因相关 Rust 格式 * chore(fmt): 统一 admin API key 路由 Rust 格式 * chore(fmt): 统一 public 路由与相关测试 Rust 格式 * fix(test): 对齐 no-execution usage 归因断言 * test(middleware): 固定 access log tracing 用例线程模型 * fix(frontend): 提取用户 API Key payload 默认并发辅助 * fix(frontend): 保留用户 Key 的 concurrent_limit 默认值 * fix(api-keys): remove hardcoded concurrent limit default --------- Co-authored-by: fawney19 <[email protected]>
This commit is contained in:
@@ -106,7 +106,7 @@
|
||||
钱包
|
||||
</TableHead>
|
||||
<TableHead class="w-[190px] h-12 font-semibold">
|
||||
统计/限速
|
||||
统计/限制
|
||||
</TableHead>
|
||||
<TableHead class="w-[110px] h-12 font-semibold">
|
||||
有效期
|
||||
@@ -239,6 +239,22 @@
|
||||
{{ formatRateLimitInheritable(apiKey.rate_limit) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1 text-muted-foreground">
|
||||
<span>并发:</span>
|
||||
<Badge
|
||||
v-if="isConcurrentLimitInherited(apiKey.concurrent_limit) || isConcurrentLimitUnlimited(apiKey.concurrent_limit)"
|
||||
variant="secondary"
|
||||
class="h-5 px-1.5 py-0 text-[10px] font-medium"
|
||||
>
|
||||
{{ formatConcurrentLimitInheritable(apiKey.concurrent_limit) }}
|
||||
</Badge>
|
||||
<span
|
||||
v-else
|
||||
class="font-medium text-foreground"
|
||||
>
|
||||
{{ formatConcurrentLimitInheritable(apiKey.concurrent_limit) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell class="py-4">
|
||||
@@ -409,6 +425,12 @@
|
||||
>
|
||||
{{ formatRateLimitInheritable(apiKey.rate_limit) }}
|
||||
</Badge>
|
||||
<Badge
|
||||
variant="secondary"
|
||||
class="h-5 px-1.5 py-0 text-[10px] font-medium"
|
||||
>
|
||||
{{ formatConcurrentLimitInheritable(apiKey.concurrent_limit) }}
|
||||
</Badge>
|
||||
<Badge
|
||||
v-if="apiKey.auto_delete_on_expiry"
|
||||
variant="secondary"
|
||||
@@ -920,6 +942,7 @@ function editApiKey(apiKey: AdminApiKey) {
|
||||
unlimited_balance: isApiKeyUnlimited(apiKey),
|
||||
expires_at: expiresAt,
|
||||
rate_limit: apiKey.rate_limit ?? undefined,
|
||||
concurrent_limit: apiKey.concurrent_limit ?? undefined,
|
||||
auto_delete_on_expiry: apiKey.auto_delete_on_expiry || false,
|
||||
allowed_providers: apiKey.allowed_providers == null ? null : [...apiKey.allowed_providers],
|
||||
allowed_api_formats: apiKey.allowed_api_formats == null ? null : [...apiKey.allowed_api_formats],
|
||||
@@ -961,6 +984,20 @@ function formatApiKeyTotalTokens(apiKey: AdminApiKey): string {
|
||||
return formatTokens(apiKey.total_tokens)
|
||||
}
|
||||
|
||||
function formatConcurrentLimitInheritable(concurrentLimit?: number | null): string {
|
||||
if (concurrentLimit == null) return '不限并发'
|
||||
if (concurrentLimit === 0) return '不限并发'
|
||||
return `${concurrentLimit} 并发`
|
||||
}
|
||||
|
||||
function isConcurrentLimitInherited(concurrentLimit?: number | null): boolean {
|
||||
return concurrentLimit == null
|
||||
}
|
||||
|
||||
function isConcurrentLimitUnlimited(concurrentLimit?: number | null): boolean {
|
||||
return concurrentLimit === 0
|
||||
}
|
||||
|
||||
function formatWalletAmount(value: number | null, nullLabel = '无限制'): string {
|
||||
if (value == null) {
|
||||
return nullLabel
|
||||
@@ -1110,6 +1147,7 @@ async function handleKeyFormSubmit(data: StandaloneKeyFormData) {
|
||||
name: data.name || undefined,
|
||||
unlimited_balance: Boolean(data.unlimited_balance),
|
||||
rate_limit: data.rate_limit ?? null, // undefined = 跟随系统默认,显式传 null
|
||||
concurrent_limit: data.concurrent_limit ?? null,
|
||||
expires_at: serializeExpiryDate(data.expires_at),
|
||||
auto_delete_on_expiry: data.auto_delete_on_expiry,
|
||||
// 空数组表示清除限制(允许全部),后端会将空数组存为 NULL
|
||||
@@ -1139,6 +1177,7 @@ async function handleKeyFormSubmit(data: StandaloneKeyFormData) {
|
||||
name: data.name || undefined,
|
||||
initial_balance_usd: isUnlimited ? null : (data.initial_balance_usd as number),
|
||||
rate_limit: data.rate_limit ?? null, // undefined = 跟随系统默认,显式传 null
|
||||
concurrent_limit: data.concurrent_limit ?? null,
|
||||
expires_at: serializeExpiryDate(data.expires_at),
|
||||
auto_delete_on_expiry: data.auto_delete_on_expiry,
|
||||
// 空数组表示不设置限制(允许全部),后端会将空数组存为 NULL
|
||||
|
||||
Reference in New Issue
Block a user