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:
@@ -77,7 +77,7 @@ const NAV: NavSection[] = [
|
||||
},
|
||||
]
|
||||
|
||||
const VERSION = '1.0.50'
|
||||
const VERSION = '1.0.51'
|
||||
|
||||
export default function Sidebar({ isOpen, onClose }: SidebarProps) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
@@ -217,6 +217,8 @@
|
||||
"selectDomains": "Domains wählen",
|
||||
"lbAlgo": "Load-Balancing",
|
||||
"lbAlgoHint": "roundrobin = gleichmäßig, leastconn = an den Server mit wenigsten Verbindungen, source = sticky per Client-IP (für stateful Apps ohne shared session).",
|
||||
"websocket": "WebSocket-Support",
|
||||
"websocketHint": "An: erlaubt langlebige WebSocket-/Long-Poll-Verbindungen (z. B. Proxmox-Console, SSH-WS, AsyncAPI) — Tunnel-Idle 1h statt 60s. Aus: strikte HTTP-Timeouts.",
|
||||
"servers": "Server",
|
||||
"noServers": "kein Server",
|
||||
"nServers": "{{n}} Server",
|
||||
|
||||
@@ -217,6 +217,8 @@
|
||||
"selectDomains": "Select domains",
|
||||
"lbAlgo": "Load balancing",
|
||||
"lbAlgoHint": "roundrobin = evenly, leastconn = pick the server with fewest active connections, source = sticky per client-IP hash (for stateful apps without shared session).",
|
||||
"websocket": "WebSocket support",
|
||||
"websocketHint": "On: allow long-lived WebSocket / long-poll connections (Proxmox console, SSH-over-WS, AsyncAPI) — tunnel idle 1h instead of 60s. Off: strict HTTP timeouts.",
|
||||
"servers": "Servers",
|
||||
"noServers": "no server",
|
||||
"nServers": "{{n}} servers",
|
||||
|
||||
@@ -22,6 +22,7 @@ interface Backend {
|
||||
scheme: string
|
||||
health_check_path?: string | null
|
||||
lb_algorithm: 'roundrobin' | 'leastconn' | 'source'
|
||||
websocket: boolean
|
||||
active: boolean
|
||||
created_at: string
|
||||
updated_at: string
|
||||
@@ -43,6 +44,7 @@ interface BackendFormValues {
|
||||
scheme: 'http' | 'https'
|
||||
health_check_path?: string
|
||||
lb_algorithm: 'roundrobin' | 'leastconn' | 'source'
|
||||
websocket: boolean
|
||||
active: boolean
|
||||
domain_ids?: number[]
|
||||
}
|
||||
@@ -193,7 +195,12 @@ export default function BackendsPage() {
|
||||
},
|
||||
{
|
||||
title: t('backends.lbAlgo'), dataIndex: 'lb_algorithm', key: 'lb',
|
||||
render: (v: string) => <Tag>{v}</Tag>,
|
||||
render: (v: string, row) => (
|
||||
<Space size={4}>
|
||||
<Tag>{v}</Tag>
|
||||
{row.websocket && <Tag color="cyan">WS</Tag>}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{ title: t('backends.healthCheck'), dataIndex: 'health_check_path', key: 'hc', render: (v?: string) => v ?? '—' },
|
||||
{
|
||||
@@ -216,6 +223,7 @@ export default function BackendsPage() {
|
||||
scheme: row.scheme as 'http' | 'https',
|
||||
health_check_path: row.health_check_path ?? undefined,
|
||||
lb_algorithm: row.lb_algorithm,
|
||||
websocket: row.websocket,
|
||||
active: row.active,
|
||||
domain_ids: domainsForBackend(row.id).map(d => d.id),
|
||||
})
|
||||
@@ -246,7 +254,7 @@ export default function BackendsPage() {
|
||||
extraActions={
|
||||
<Button type="primary" icon={<PlusOutlined />} onClick={() => {
|
||||
setCreating(true); form.resetFields()
|
||||
form.setFieldsValue({ scheme: 'http', lb_algorithm: 'roundrobin', active: true })
|
||||
form.setFieldsValue({ scheme: 'http', lb_algorithm: 'roundrobin', websocket: false, active: true })
|
||||
}}>
|
||||
{t('backends.addBackend')}
|
||||
</Button>
|
||||
@@ -294,6 +302,10 @@ export default function BackendsPage() {
|
||||
<Form.Item label={t('backends.healthCheck')} name="health_check_path">
|
||||
<Input placeholder="/health" />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('backends.websocket')} name="websocket" valuePropName="checked"
|
||||
extra={t('backends.websocketHint')}>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('backends.active')} name="active" valuePropName="checked">
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
|
||||
Reference in New Issue
Block a user