feat(routing): make client disconnect behavior strategy-scoped

This commit is contained in:
elky
2026-09-08 23:11:37 +08:00
parent 99f6499b2b
commit e58570d79d
22 changed files with 1156 additions and 240 deletions
@@ -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,
}
}