mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-05 00:47:48 +08:00
feat(routing): make client disconnect behavior strategy-scoped
This commit is contained in:
@@ -24,6 +24,20 @@ describe('routingPolicy', () => {
|
||||
|
||||
expect(config.default_policy.priority_mode).toBe('provider')
|
||||
expect(config.default_policy.scheduling_mode).toBe('cache_affinity')
|
||||
expect(config.default_policy.cancel_on_client_disconnect).toBe(false)
|
||||
})
|
||||
|
||||
it('preserves cancellation policy across model scheduling edits', () => {
|
||||
const config = createEmptyRoutingGroupConfig()
|
||||
config.default_policy.cancel_on_client_disconnect = true
|
||||
const updated = upsertModelSchedulingRule(config, 'gpt-5', {
|
||||
priority_mode: 'global_key',
|
||||
scheduling_mode: 'fixed_order',
|
||||
})
|
||||
expect(normalizeRoutingGroupConfig(updated).default_policy.cancel_on_client_disconnect).toBe(true)
|
||||
expect(getModelScheduling(updated, 'gpt-5').cancel_on_client_disconnect).toBe(true)
|
||||
expect(getModelScheduling(updated, 'other-model').cancel_on_client_disconnect).toBe(true)
|
||||
expect(createEmptyRoutingGroupConfig().default_policy.cancel_on_client_disconnect).toBe(false)
|
||||
})
|
||||
|
||||
it('drops the legacy group model allowlist while normalizing config', () => {
|
||||
@@ -77,7 +91,7 @@ describe('routingPolicy', () => {
|
||||
expect(createEmptyRoutingGroupConfig().default_policy.sticky_key_attempts).toBe(2)
|
||||
expect(normalizeRoutingGroupConfig({}).default_policy.sticky_key_attempts).toBe(2)
|
||||
expect(normalizeRoutingGroupConfig({
|
||||
default_policy: { priority_mode: 'provider', scheduling_mode: 'cache_affinity', keep_priority_on_conversion: false, sticky_key_attempts: 3, enable_cf_heartbeat: false, cyber_continue_failover: false },
|
||||
default_policy: { priority_mode: 'provider', scheduling_mode: 'cache_affinity', keep_priority_on_conversion: false, sticky_key_attempts: 3, enable_cf_heartbeat: false, cyber_continue_failover: false, cancel_on_client_disconnect: false },
|
||||
}).default_policy.sticky_key_attempts).toBe(3)
|
||||
expect(normalizeStickyKeyAttempts('5')).toBe(5)
|
||||
expect(normalizeStickyKeyAttempts(-1)).toBe(2)
|
||||
|
||||
@@ -12,6 +12,7 @@ export interface RoutingDefaultPolicy {
|
||||
keep_priority_on_conversion: boolean
|
||||
enable_cf_heartbeat: boolean
|
||||
cyber_continue_failover: boolean
|
||||
cancel_on_client_disconnect: boolean
|
||||
/** 首个候选的总尝试次数;后续候选始终只尝试 1 次。0 或 1 表示不重试 */
|
||||
sticky_key_attempts: number
|
||||
}
|
||||
@@ -78,6 +79,7 @@ export function createEmptyRoutingGroupConfig(): RoutingGroupConfig {
|
||||
keep_priority_on_conversion: false,
|
||||
enable_cf_heartbeat: false,
|
||||
cyber_continue_failover: false,
|
||||
cancel_on_client_disconnect: false,
|
||||
sticky_key_attempts: DEFAULT_STICKY_KEY_ATTEMPTS,
|
||||
},
|
||||
model_policies: [],
|
||||
@@ -374,6 +376,7 @@ export function getModelScheduling(
|
||||
keep_priority_on_conversion: normalized.default_policy.keep_priority_on_conversion,
|
||||
enable_cf_heartbeat: normalized.default_policy.enable_cf_heartbeat,
|
||||
cyber_continue_failover: normalized.default_policy.cyber_continue_failover,
|
||||
cancel_on_client_disconnect: normalized.default_policy.cancel_on_client_disconnect,
|
||||
sticky_key_attempts: action?.sticky_key_attempts ?? normalized.default_policy.sticky_key_attempts,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +114,8 @@ export const legacyAdminEnglishMessages: Record<string, string> = {
|
||||
'错误重试次数': 'Error retry count',
|
||||
'CF保持心跳': 'CF keepalive',
|
||||
'Cyber继续转移': 'Fail over on Cyber errors',
|
||||
'取消请求立即打断': 'Abort immediately on client cancellation',
|
||||
'默认关闭:客户端取消或断开后,服务端继续等待请求完成并正常计费。开启后立即打断且不计费,按次计费的请求仍收取单次请求费用。仅作用于当前调度策略。': 'Off by default: after client cancellation or disconnection, the server completes the request and bills normally. When enabled, requests are aborted immediately without usage charges, except for per-request fees. Applies only to this routing policy.',
|
||||
'调度配置': 'Routing configuration',
|
||||
'先选择调度维度,再配置优先级模式、调度策略和提供商排序。': 'Choose the routing scope, then configure the priority mode, routing strategy, and provider order.',
|
||||
'调度维度': 'Routing scope',
|
||||
|
||||
@@ -402,7 +402,7 @@
|
||||
这些选项作用于当前调度策略。
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 gap-2 md:grid-cols-2 xl:grid-cols-4">
|
||||
<div class="grid auto-rows-fr grid-cols-1 gap-2 md:grid-cols-2 xl:grid-cols-4">
|
||||
<div
|
||||
class="order-1 flex min-h-12 items-center justify-between gap-3 rounded-lg border border-border/60 px-3 py-2 text-sm"
|
||||
data-testid="keep-priority-on-conversion"
|
||||
@@ -479,6 +479,24 @@
|
||||
@update:model-value="updateExecutionPolicy('cyber_continue_failover', $event)"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="order-5 flex min-h-12 items-center justify-between gap-3 rounded-lg border border-border/60 px-3 py-2 text-sm"
|
||||
data-testid="cancel-on-client-disconnect"
|
||||
>
|
||||
<div class="flex min-w-0 items-center gap-1.5">
|
||||
<span class="font-medium">取消请求立即打断</span>
|
||||
<HelpHint
|
||||
label="取消请求立即打断"
|
||||
text="默认关闭:客户端取消或断开后,服务端继续等待请求完成并正常计费。开启后立即打断且不计费,按次计费的请求仍收取单次请求费用。仅作用于当前调度策略。"
|
||||
/>
|
||||
</div>
|
||||
<Switch
|
||||
:model-value="cancelOnClientDisconnect"
|
||||
:disabled="saving"
|
||||
aria-label="取消请求立即打断"
|
||||
@update:model-value="updateExecutionPolicy('cancel_on_client_disconnect', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -970,6 +988,9 @@ const cfHeartbeat = computed<boolean>(() => (
|
||||
const cyberContinueFailover = computed<boolean>(() => (
|
||||
draft.value?.config_json.default_policy.cyber_continue_failover ?? false
|
||||
))
|
||||
const cancelOnClientDisconnect = computed<boolean>(() => (
|
||||
draft.value?.config_json.default_policy.cancel_on_client_disconnect ?? false
|
||||
))
|
||||
interface ModelRow {
|
||||
name: string
|
||||
displayName: string
|
||||
@@ -1306,7 +1327,7 @@ function updateKeepPriorityOnConversion(value: boolean): void {
|
||||
}
|
||||
|
||||
function updateExecutionPolicy(
|
||||
field: 'enable_cf_heartbeat' | 'cyber_continue_failover',
|
||||
field: 'enable_cf_heartbeat' | 'cyber_continue_failover' | 'cancel_on_client_disconnect',
|
||||
value: boolean,
|
||||
): void {
|
||||
if (!draft.value) return
|
||||
|
||||
Reference in New Issue
Block a user