将 Worker 发现、路由画像、容量与执行传输抽象为平台无关接口,新增 Kubernetes 和静态容量适配器,并以 shadow 模式接入生产配置。 实现网络与容量评分、路由防抖、池队列、同步 Worker 租约、一次性执行令牌,以及提交状态不明时禁止重复分配的安全语义。 新增 0105 兼容迁移、管理接口、指标、OpenAPI 和回归测试。已执行全量 Go 测试、go vet、OpenAPI、迁移安全、Compose 与 Kustomize 验证。
193 lines
8.0 KiB
SQL
193 lines
8.0 KiB
SQL
CREATE TABLE IF NOT EXISTS gateway_execution_pools (
|
|
pool_id text PRIMARY KEY,
|
|
labels jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
capabilities jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
state text NOT NULL DEFAULT 'active',
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
CONSTRAINT gateway_execution_pools_id_check
|
|
CHECK (pool_id ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$'),
|
|
CONSTRAINT gateway_execution_pools_state_check
|
|
CHECK (state IN ('active', 'draining', 'disabled')),
|
|
CONSTRAINT gateway_execution_pools_labels_object_check
|
|
CHECK (jsonb_typeof(labels) = 'object'),
|
|
CONSTRAINT gateway_execution_pools_capabilities_object_check
|
|
CHECK (jsonb_typeof(capabilities) = 'object')
|
|
);
|
|
|
|
INSERT INTO gateway_execution_pools (pool_id, labels)
|
|
VALUES ('legacy-default', '{"migration":"legacy"}'::jsonb)
|
|
ON CONFLICT (pool_id) DO NOTHING;
|
|
|
|
INSERT INTO gateway_execution_pools (pool_id, labels)
|
|
SELECT DISTINCT site, jsonb_build_object('legacy_site', site)
|
|
FROM gateway_worker_instances
|
|
WHERE NULLIF(site, '') IS NOT NULL
|
|
ON CONFLICT (pool_id) DO NOTHING;
|
|
|
|
ALTER TABLE gateway_worker_instances
|
|
ADD COLUMN pool_id text DEFAULT 'legacy-default',
|
|
ADD COLUMN worker_id text DEFAULT '',
|
|
ADD COLUMN endpoint text DEFAULT '',
|
|
ADD COLUMN orchestrator_instance_ref text DEFAULT '',
|
|
ADD COLUMN labels jsonb DEFAULT '{}'::jsonb,
|
|
ADD COLUMN capabilities jsonb DEFAULT '{}'::jsonb,
|
|
ADD COLUMN protocol_version text DEFAULT 'v1';
|
|
|
|
UPDATE gateway_worker_instances
|
|
SET pool_id = site
|
|
WHERE NULLIF(site, '') IS NOT NULL
|
|
AND pool_id = 'legacy-default';
|
|
|
|
UPDATE gateway_worker_instances
|
|
SET worker_id = instance_id
|
|
WHERE worker_id = '';
|
|
|
|
UPDATE gateway_worker_instances
|
|
SET orchestrator_instance_ref = pod_name
|
|
WHERE orchestrator_instance_ref = ''
|
|
AND NULLIF(pod_name, '') IS NOT NULL;
|
|
|
|
ALTER TABLE gateway_worker_instances
|
|
ADD CONSTRAINT gateway_worker_instances_pool_fk
|
|
FOREIGN KEY (pool_id) REFERENCES gateway_execution_pools(pool_id) ON DELETE RESTRICT,
|
|
ADD CONSTRAINT gateway_worker_instances_routing_fields_not_null_check
|
|
CHECK (num_nonnulls(pool_id, worker_id, endpoint, orchestrator_instance_ref, labels, capabilities, protocol_version) = 7) NOT VALID,
|
|
ADD CONSTRAINT gateway_worker_instances_labels_object_check
|
|
CHECK (jsonb_typeof(labels) = 'object') NOT VALID,
|
|
ADD CONSTRAINT gateway_worker_instances_capabilities_object_check
|
|
CHECK (jsonb_typeof(capabilities) = 'object') NOT VALID;
|
|
|
|
ALTER TABLE gateway_worker_instances
|
|
VALIDATE CONSTRAINT gateway_worker_instances_routing_fields_not_null_check;
|
|
|
|
ALTER TABLE gateway_worker_instances
|
|
VALIDATE CONSTRAINT gateway_worker_instances_labels_object_check;
|
|
|
|
ALTER TABLE gateway_worker_instances
|
|
VALIDATE CONSTRAINT gateway_worker_instances_capabilities_object_check;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_worker_instances_pool_heartbeat
|
|
ON gateway_worker_instances(pool_id, status, heartbeat_at, instance_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_route_health (
|
|
pool_id text NOT NULL REFERENCES gateway_execution_pools(pool_id) ON DELETE CASCADE,
|
|
route_profile_key text NOT NULL,
|
|
state text NOT NULL DEFAULT 'unknown',
|
|
success_rate double precision NOT NULL DEFAULT 0,
|
|
connect_tls_p95_ms bigint NOT NULL DEFAULT 0,
|
|
first_byte_p95_ms bigint NOT NULL DEFAULT 0,
|
|
upload_bytes_per_second double precision NOT NULL DEFAULT 0,
|
|
jitter_p95_ms bigint NOT NULL DEFAULT 0,
|
|
consecutive_failures integer NOT NULL DEFAULT 0,
|
|
consecutive_successes integer NOT NULL DEFAULT 0,
|
|
sample_count integer NOT NULL DEFAULT 0,
|
|
sampled_at timestamptz NOT NULL,
|
|
expires_at timestamptz NOT NULL,
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
PRIMARY KEY (pool_id, route_profile_key),
|
|
CONSTRAINT gateway_route_health_state_check
|
|
CHECK (state IN ('healthy', 'degraded', 'unreachable', 'unknown')),
|
|
CONSTRAINT gateway_route_health_values_check
|
|
CHECK (
|
|
success_rate >= 0 AND success_rate <= 1
|
|
AND connect_tls_p95_ms >= 0
|
|
AND first_byte_p95_ms >= 0
|
|
AND upload_bytes_per_second >= 0
|
|
AND jitter_p95_ms >= 0
|
|
AND consecutive_failures >= 0
|
|
AND consecutive_successes >= 0
|
|
AND sample_count >= 0
|
|
AND expires_at >= sampled_at
|
|
)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_route_health_fresh
|
|
ON gateway_route_health(route_profile_key, expires_at, state, pool_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_route_preferences (
|
|
route_profile_key text PRIMARY KEY,
|
|
current_pool_id text NOT NULL DEFAULT '',
|
|
current_since timestamptz,
|
|
challenger_pool_id text NOT NULL DEFAULT '',
|
|
challenger_wins integer NOT NULL DEFAULT 0,
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
CONSTRAINT gateway_route_preferences_wins_check CHECK (challenger_wins >= 0)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_route_probe_requests (
|
|
route_profile_key text PRIMARY KEY,
|
|
requested_at timestamptz NOT NULL DEFAULT now(),
|
|
expires_at timestamptz NOT NULL DEFAULT now() + interval '30 seconds'
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_route_probe_requests_due
|
|
ON gateway_route_probe_requests(expires_at, requested_at);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_pool_capacity_desires (
|
|
pool_id text PRIMARY KEY REFERENCES gateway_execution_pools(pool_id) ON DELETE CASCADE,
|
|
desired integer NOT NULL,
|
|
reason text NOT NULL DEFAULT '',
|
|
valid_until timestamptz NOT NULL,
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
CONSTRAINT gateway_pool_capacity_desires_value_check CHECK (desired >= 0)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS gateway_worker_execution_leases (
|
|
lease_id uuid PRIMARY KEY,
|
|
task_id uuid NOT NULL REFERENCES gateway_tasks(id) ON DELETE CASCADE,
|
|
pool_id text NOT NULL REFERENCES gateway_execution_pools(pool_id) ON DELETE RESTRICT,
|
|
worker_id text NOT NULL,
|
|
instance_id text NOT NULL REFERENCES gateway_worker_instances(instance_id) ON DELETE CASCADE,
|
|
nonce_hash text NOT NULL UNIQUE,
|
|
state text NOT NULL DEFAULT 'reserved',
|
|
expires_at timestamptz NOT NULL,
|
|
released_at timestamptz,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
CONSTRAINT gateway_worker_execution_leases_state_check
|
|
CHECK (state IN ('reserved', 'running', 'released', 'expired'))
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_worker_execution_leases_active
|
|
ON gateway_worker_execution_leases(pool_id, instance_id, expires_at)
|
|
WHERE released_at IS NULL;
|
|
|
|
ALTER TABLE gateway_tasks
|
|
ADD COLUMN assigned_pool_id text,
|
|
ADD COLUMN assigned_worker_id text,
|
|
ADD COLUMN route_profile_key text,
|
|
ADD COLUMN routing_platform_id uuid,
|
|
ADD COLUMN routing_platform_model_id uuid,
|
|
ADD COLUMN routing_version text,
|
|
ADD COLUMN routing_reason text,
|
|
ADD COLUMN routing_snapshot jsonb,
|
|
ADD COLUMN submission_state text DEFAULT 'not_started';
|
|
|
|
ALTER TABLE gateway_tasks
|
|
ADD CONSTRAINT gateway_tasks_assigned_pool_fk
|
|
FOREIGN KEY (assigned_pool_id) REFERENCES gateway_execution_pools(pool_id) ON DELETE SET NULL,
|
|
ADD CONSTRAINT gateway_tasks_routing_platform_fk
|
|
FOREIGN KEY (routing_platform_id) REFERENCES integration_platforms(id) ON DELETE SET NULL,
|
|
ADD CONSTRAINT gateway_tasks_routing_platform_model_fk
|
|
FOREIGN KEY (routing_platform_model_id) REFERENCES platform_models(id) ON DELETE SET NULL,
|
|
ADD CONSTRAINT gateway_tasks_routing_snapshot_object_check
|
|
CHECK (routing_snapshot IS NULL OR jsonb_typeof(routing_snapshot) = 'object') NOT VALID,
|
|
ADD CONSTRAINT gateway_tasks_submission_state_not_null_check
|
|
CHECK (num_nonnulls(submission_state) = 1) NOT VALID,
|
|
ADD CONSTRAINT gateway_tasks_submission_state_check
|
|
CHECK (submission_state IN ('not_started', 'submitting', 'submitted', 'submission_confirmation_pending', 'completed')) NOT VALID;
|
|
|
|
ALTER TABLE gateway_tasks
|
|
VALIDATE CONSTRAINT gateway_tasks_submission_state_not_null_check;
|
|
|
|
ALTER TABLE gateway_tasks
|
|
VALIDATE CONSTRAINT gateway_tasks_routing_snapshot_object_check;
|
|
|
|
ALTER TABLE gateway_tasks
|
|
VALIDATE CONSTRAINT gateway_tasks_submission_state_check;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gateway_tasks_assigned_pool_queue
|
|
ON gateway_tasks(assigned_pool_id, status, next_run_at, priority, created_at)
|
|
WHERE async_mode = true AND status = 'queued';
|