feat(backends): WebSocket-Toggle pro Backend

Migration 0017 fügt backends.websocket BOOL. Wenn aktiv emittiert der
HAProxy-Renderer `timeout tunnel 1h` IM Backend-Block; defaults-Section
hat den Global-Timeout dafür verloren. Backends ohne WS-Workload bleiben
bei strikten HTTP-Timeouts (Connection-Hygiene). Migrations-Heuristik
schaltet vm-pool/proxmox/console/vnc-Namen auto auf true damit Proxmox-
Konsole nach Deploy weiterhin durchläuft.

UI: Switch im Backend-Modal + WS-Tag in der Übersichtstabelle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-11 21:51:09 +02:00
parent da35097041
commit 26f321de9d
13 changed files with 108 additions and 24 deletions

View File

@@ -1,7 +1,7 @@
// Package backends implements CRUD against the `backends` table.
// Ein Backend ist ein Pool — Name, Scheme, Healthcheck, LB-Algorithm.
// Die konkreten Upstream-Server liegen in backend_servers (siehe
// services/backendservers).
// Ein Backend ist ein Pool — Name, Scheme, Healthcheck, LB-Algorithm,
// WebSocket-Flag. Die konkreten Upstream-Server liegen in
// backend_servers (siehe services/backendservers).
package backends
import (
@@ -23,7 +23,7 @@ type Repo struct {
func New(pool *pgxpool.Pool) *Repo { return &Repo{Pool: pool} }
const baseSelect = `
SELECT id, name, scheme, health_check_path, lb_algorithm, active,
SELECT id, name, scheme, health_check_path, lb_algorithm, websocket, active,
created_at, updated_at
FROM backends
`
@@ -62,11 +62,11 @@ func (r *Repo) Create(ctx context.Context, b models.Backend) (*models.Backend, e
b.LBAlgorithm = "roundrobin"
}
row := r.Pool.QueryRow(ctx, `
INSERT INTO backends (name, scheme, health_check_path, lb_algorithm, active)
VALUES ($1, $2, $3, $4, $5)
RETURNING id, name, scheme, health_check_path, lb_algorithm, active,
INSERT INTO backends (name, scheme, health_check_path, lb_algorithm, websocket, active)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, name, scheme, health_check_path, lb_algorithm, websocket, active,
created_at, updated_at`,
b.Name, b.Scheme, b.HealthCheckPath, b.LBAlgorithm, b.Active)
b.Name, b.Scheme, b.HealthCheckPath, b.LBAlgorithm, b.WebSocket, b.Active)
return scanBackend(row)
}
@@ -80,12 +80,13 @@ UPDATE backends SET
scheme = $2,
health_check_path = $3,
lb_algorithm = $4,
active = $5,
websocket = $5,
active = $6,
updated_at = NOW()
WHERE id = $6
RETURNING id, name, scheme, health_check_path, lb_algorithm, active,
WHERE id = $7
RETURNING id, name, scheme, health_check_path, lb_algorithm, websocket, active,
created_at, updated_at`,
b.Name, b.Scheme, b.HealthCheckPath, b.LBAlgorithm, b.Active, id)
b.Name, b.Scheme, b.HealthCheckPath, b.LBAlgorithm, b.WebSocket, b.Active, id)
out, err := scanBackend(row)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
@@ -111,7 +112,7 @@ func scanBackend(row interface{ Scan(...any) error }) (*models.Backend, error) {
var b models.Backend
if err := row.Scan(
&b.ID, &b.Name, &b.Scheme,
&b.HealthCheckPath, &b.LBAlgorithm, &b.Active,
&b.HealthCheckPath, &b.LBAlgorithm, &b.WebSocket, &b.Active,
&b.CreatedAt, &b.UpdatedAt,
); err != nil {
return nil, err