mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-14 11:12:17 +03:00
native proxy-pool round-robin / egress IP rotation (#6365) (net +1/-0, tests OK). Integrated into release/v3.8.46.
54 lines
2.5 KiB
SQL
54 lines
2.5 KiB
SQL
-- Migration 117: native proxy-pool round-robin / egress IP rotation (#6365)
|
|
--
|
|
-- Lifts the UNIQUE(scope, scope_id) hard constraint on proxy_assignments so N
|
|
-- proxies can attach to a single scope as a POOL, and adds a per-assignment
|
|
-- `position` ordering column. A companion `proxy_scope_rotation` table holds the
|
|
-- per-scope rotation strategy plus the persisted monotonic round-robin cursor.
|
|
--
|
|
-- Backward-compatible: existing single assignments are copied verbatim and become
|
|
-- a pool of size 1 (position 0). The alive-predicate + #6246 fail-closed guard are
|
|
-- untouched — an empty / all-dead pool still resolves to null (never direct egress).
|
|
--
|
|
-- SQLite cannot DROP a table-level UNIQUE constraint in place, so the assignments
|
|
-- table is rebuilt via the canonical rename/copy/drop pattern. The whole file runs
|
|
-- inside the migration runner's per-file transaction (all-or-nothing). Idempotency
|
|
-- is guarded by isSchemaAlreadyApplied(case "117") → proxy_assignments.position.
|
|
|
|
ALTER TABLE proxy_assignments RENAME TO proxy_assignments_pre117;
|
|
|
|
CREATE TABLE proxy_assignments (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
proxy_id TEXT NOT NULL,
|
|
scope TEXT NOT NULL,
|
|
scope_id TEXT,
|
|
position INTEGER NOT NULL DEFAULT 0,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
UNIQUE(scope, scope_id, proxy_id),
|
|
FOREIGN KEY (proxy_id) REFERENCES proxy_registry(id) ON DELETE RESTRICT
|
|
);
|
|
|
|
INSERT INTO proxy_assignments (id, proxy_id, scope, scope_id, position, created_at, updated_at)
|
|
SELECT id, proxy_id, scope, scope_id, 0, created_at, updated_at
|
|
FROM proxy_assignments_pre117;
|
|
|
|
DROP TABLE proxy_assignments_pre117;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_proxy_assignments_proxy_id ON proxy_assignments(proxy_id);
|
|
CREATE INDEX IF NOT EXISTS idx_proxy_assignments_scope ON proxy_assignments(scope, scope_id);
|
|
|
|
-- Per-scope rotation state. scope_id is normalized ('__global__' for the global
|
|
-- scope) so the primary key is always non-null. `cursor` is the monotonic
|
|
-- round-robin counter (never Math.random); `rotated_at` + `sticky_window_minutes`
|
|
-- support a future sticky strategy without another migration.
|
|
CREATE TABLE IF NOT EXISTS proxy_scope_rotation (
|
|
scope TEXT NOT NULL,
|
|
scope_id TEXT NOT NULL,
|
|
strategy TEXT NOT NULL DEFAULT 'round-robin',
|
|
cursor INTEGER NOT NULL DEFAULT 0,
|
|
sticky_window_minutes INTEGER NOT NULL DEFAULT 30,
|
|
rotated_at TEXT,
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
PRIMARY KEY (scope, scope_id)
|
|
);
|