Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Model Groups provide logical model names that map to multiple physical models across providers, with automatic failover when one provider's key pool is exhausted. Backend: - New model_groups + model_group_members tables with FK constraints - Full CRUD API (7 endpoints) with admin-only write permissions - Cache layer: DashMap-backed CachedModelGroup with load_from_db - Relay integration: ModelResolution enum for Direct/Group routing - Cross-provider failover: sort_candidates_by_quota + OnceLock cache - Relay failure path: record failure usage + relay_dequeue (fixes queue counter leak that caused connection pool exhaustion) - add_group_member: validate model_id exists before insert Frontend: - saas-relay-client: accept getModel() callback for dynamic model selection - connectionStore: prefer conversationStore.currentModel over first available Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
33 lines
1.4 KiB
SQL
33 lines
1.4 KiB
SQL
-- Model Groups: logical model abstraction for cross-provider failover
|
|
--
|
|
-- A model group maps a logical name (e.g. "coding") to multiple physical models
|
|
-- across different providers. When one provider's key pool is exhausted,
|
|
-- the relay automatically falls over to the next provider.
|
|
--
|
|
-- Routing strategy "quota_aware" sorts candidates by remaining RPM/TPM capacity.
|
|
|
|
CREATE TABLE IF NOT EXISTS model_groups (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL UNIQUE,
|
|
display_name TEXT NOT NULL DEFAULT '',
|
|
description TEXT NOT NULL DEFAULT '',
|
|
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
|
failover_strategy TEXT NOT NULL DEFAULT 'quota_aware',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS model_group_members (
|
|
id TEXT PRIMARY KEY,
|
|
group_id TEXT NOT NULL REFERENCES model_groups(id) ON DELETE CASCADE,
|
|
provider_id TEXT NOT NULL REFERENCES providers(id) ON DELETE CASCADE,
|
|
model_id TEXT NOT NULL,
|
|
priority INTEGER NOT NULL DEFAULT 0,
|
|
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_mgm_group ON model_group_members(group_id);
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_mgm_unique ON model_group_members(group_id, provider_id, model_id);
|