feat(backends): Pool-Modell — Backend = Pool, N Server pro Backend
Migration 0016: backend_servers (id, backend_id, name, address, port, weight, backup, active) + backends.lb_algorithm. Daten-Migration kopiert bestehende backends.address/port als ersten Server, dann DROP COLUMN. HAProxy-Renderer: rendert pro Backend einen Block mit `balance <algo>` + N `server`-Zeilen (weight, backup-Flag, optional check inter 5s). LB-Algorithmen: roundrobin / leastconn / source. REST: /backends/:id/servers (GET/POST), /backend-servers/:id (PUT/DELETE). Re-rendert HAProxy nach jeder Server-Mutation. UI: address/port aus Backend-Form raus, lb_algorithm-Select rein. Server verwaltet ein expandable Sub-Panel pro Backend-Row (Tabelle + Add/Edit/ Delete-Modal). Domain-Attachment-Multi-Select bleibt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
81
internal/database/migrations/0016_backend_servers.sql
Normal file
81
internal/database/migrations/0016_backend_servers.sql
Normal file
@@ -0,0 +1,81 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
|
||||
-- v1.0.49: backends wird vom Single-Server-Endpoint zum Pool.
|
||||
-- Bisher: backends.address/port → genau ein Upstream.
|
||||
-- Jetzt: backends = Pool-Definition (LB-Algo, Healthcheck), die
|
||||
-- konkreten Upstreams leben in backend_servers (1:N).
|
||||
-- Damit kann eine Domain → ein Backend → N Server (HAProxy macht
|
||||
-- den Loadbalance laut backends.lb_algorithm).
|
||||
|
||||
CREATE TABLE IF NOT EXISTS backend_servers (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
backend_id BIGINT NOT NULL REFERENCES backends(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
address TEXT NOT NULL,
|
||||
port INTEGER NOT NULL,
|
||||
weight INTEGER NOT NULL DEFAULT 100,
|
||||
backup BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT backend_servers_name_unique UNIQUE (backend_id, name),
|
||||
CONSTRAINT backend_servers_port_check CHECK (port > 0 AND port < 65536),
|
||||
CONSTRAINT backend_servers_weight_check CHECK (weight >= 0 AND weight <= 256)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_backend_servers_backend
|
||||
ON backend_servers (backend_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_backend_servers_active
|
||||
ON backend_servers (backend_id, active) WHERE active;
|
||||
|
||||
-- LB-Algorithmus pro Backend. Default roundrobin entspricht haproxy-
|
||||
-- default; source = sticky-per-Source-IP (für stateful Apps ohne
|
||||
-- shared session store).
|
||||
ALTER TABLE backends
|
||||
ADD COLUMN IF NOT EXISTS lb_algorithm TEXT NOT NULL DEFAULT 'roundrobin';
|
||||
|
||||
ALTER TABLE backends
|
||||
DROP CONSTRAINT IF EXISTS backends_lb_check;
|
||||
ALTER TABLE backends
|
||||
ADD CONSTRAINT backends_lb_check
|
||||
CHECK (lb_algorithm IN ('roundrobin', 'leastconn', 'source'));
|
||||
|
||||
-- Daten-Migration: jede bisherige backends-Row produziert genau eine
|
||||
-- backend_servers-Row mit demselben address/port. name = backends.name
|
||||
-- damit der HAProxy-server-id stabil bleibt (haproxy stats / logs
|
||||
-- referenzieren ihn). Idempotent — bei Re-Apply gibt's einen Skip
|
||||
-- über das Unique-Constraint.
|
||||
INSERT INTO backend_servers (backend_id, name, address, port, active)
|
||||
SELECT id, name, address, port, active
|
||||
FROM backends
|
||||
WHERE address IS NOT NULL AND port IS NOT NULL
|
||||
ON CONFLICT (backend_id, name) DO NOTHING;
|
||||
|
||||
-- Erst nach erfolgreichem Insert die alten Spalten droppen. Wenn die
|
||||
-- Migration mittendrin abbricht, sind die Daten in beiden Tabellen
|
||||
-- vorhanden — wir verlieren nichts.
|
||||
ALTER TABLE backends DROP COLUMN IF EXISTS address;
|
||||
ALTER TABLE backends DROP COLUMN IF EXISTS port;
|
||||
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
ALTER TABLE backends ADD COLUMN IF NOT EXISTS address TEXT;
|
||||
ALTER TABLE backends ADD COLUMN IF NOT EXISTS port INTEGER;
|
||||
|
||||
UPDATE backends b
|
||||
SET address = bs.address,
|
||||
port = bs.port
|
||||
FROM (
|
||||
SELECT DISTINCT ON (backend_id) backend_id, address, port
|
||||
FROM backend_servers
|
||||
ORDER BY backend_id, id ASC
|
||||
) bs
|
||||
WHERE b.id = bs.backend_id;
|
||||
|
||||
ALTER TABLE backends DROP CONSTRAINT IF EXISTS backends_lb_check;
|
||||
ALTER TABLE backends DROP COLUMN IF EXISTS lb_algorithm;
|
||||
DROP TABLE IF EXISTS backend_servers;
|
||||
-- +goose StatementEnd
|
||||
Reference in New Issue
Block a user