Env names in reload diff; monitor shows last VRAM check result; harden control channel against floods

- diffConfig reports the env var names (from new struct tags) instead of
  Go field names, so the reload-env reply names what the user can change
- the monitor's GPU line now shows the game detector's last finding
  (external holders or none) and how long ago the check ran
- control channel: 10s per-connection watchdog (abortive force-close),
  cap of 32 concurrent connections, reload-env rate-limited; command
  read was already capped at 4 KiB
This commit is contained in:
mram
2026-09-22 09:24:27 +02:00
parent 4bd5f34ce7
commit 8fccd333aa
8 changed files with 288 additions and 66 deletions
+40 -38
View File
@@ -13,43 +13,45 @@ import (
"time"
)
// Config holds every gpu-turnstile setting.
// Config holds every gpu-turnstile setting. Each field's env tag names the
// environment variable / config-file key that sets it; user-facing output
// (e.g. the reload diff) uses those names, never the Go field names.
type Config struct {
ListenOllama string
ListenComfy string
OllamaURL string
ComfyURL string
UnloadTimeout time.Duration
JobTimeout time.Duration
LLMWaitTimeout time.Duration
ListenOllama string `env:"LISTEN_OLLAMA"`
ListenComfy string `env:"LISTEN_COMFY"`
OllamaURL string `env:"OLLAMA_URL"`
ComfyURL string `env:"COMFY_URL"`
UnloadTimeout time.Duration `env:"UNLOAD_TIMEOUT"`
JobTimeout time.Duration `env:"JOB_TIMEOUT"`
LLMWaitTimeout time.Duration `env:"LLM_WAIT_TIMEOUT"`
UnloadPollInterval time.Duration
HistoryPollInterval time.Duration
ProbeTimeout time.Duration
HealthInterval time.Duration
FreeTimeout time.Duration
WarmTimeout time.Duration
ShutdownTimeout time.Duration
BackoffInitial time.Duration
BackoffMax time.Duration
PromptCaptureLimit int64
UnloadPollInterval time.Duration `env:"UNLOAD_POLL_INTERVAL"`
HistoryPollInterval time.Duration `env:"HISTORY_POLL_INTERVAL"`
ProbeTimeout time.Duration `env:"PROBE_TIMEOUT"`
HealthInterval time.Duration `env:"HEALTH_INTERVAL"`
FreeTimeout time.Duration `env:"FREE_TIMEOUT"`
WarmTimeout time.Duration `env:"WARM_TIMEOUT"`
ShutdownTimeout time.Duration `env:"SHUTDOWN_TIMEOUT"`
BackoffInitial time.Duration `env:"BACKOFF_INITIAL"`
BackoffMax time.Duration `env:"BACKOFF_MAX"`
PromptCaptureLimit int64 `env:"PROMPT_CAPTURE_LIMIT"`
AutoUpdate bool
UpdateInterval time.Duration
UpdateRepo string
UpdateAsset string
AutoUpdate bool `env:"AUTO_UPDATE"`
UpdateInterval time.Duration `env:"UPDATE_INTERVAL"`
UpdateRepo string `env:"UPDATE_REPO"`
UpdateAsset string `env:"UPDATE_ASSET"`
// AppVersion is the version the user wants to run: "dev" disables
// updates, "stable" tracks the latest release, anything else is an
// exact vX.Y.Z release to pin. From APP_VER; defaults to "stable".
AppVersion string
AppVersion string `env:"APP_VER"`
// LLMBusyMode is "wait" (hold requests until the lock is free or
// LLMWaitTimeout expires) or "reject" (immediately answer with
// LLMBusyStatus + Retry-After when an image job is active or pending).
LLMBusyMode string
LLMBusyStatus int
BusyRetryAfter int
LLMBusyMode string `env:"LLM_BUSY_MODE"`
LLMBusyStatus int `env:"LLM_BUSY_STATUS"`
BusyRetryAfter int `env:"BUSY_RETRY_AFTER"`
// ComfyCmd spawns and supervises a ComfyUI server on demand. When
// ComfyCmd is empty but ComfyDir is set, management is enabled with the
@@ -59,10 +61,10 @@ type Config struct {
// set explicitly. The managed server is stopped after ComfyIdleTimeout
// without requests, freeing its VRAM; ComfyStartTimeout bounds how long
// a request waits for it to come up.
ComfyCmd string
ComfyDir string
ComfyIdleTimeout time.Duration
ComfyStartTimeout time.Duration
ComfyCmd string `env:"COMFY_CMD"`
ComfyDir string `env:"COMFY_DIR"`
ComfyIdleTimeout time.Duration `env:"COMFY_IDLE_TIMEOUT"`
ComfyStartTimeout time.Duration `env:"COMFY_START_TIMEOUT"`
// GameProcs (GAME_PROCS) is a watch list of process names; while any of
// them runs, the GPU is treated as held by a foreign process. The
@@ -70,15 +72,15 @@ type Config struct {
// when a process not in GPUIgnoreProcs (GPU_IGNORE_PROCS) holds more than
// that many MiB of VRAM. GamePollInterval (GAME_POLL_INTERVAL) is how
// often both checks run.
GameProcs []string
GPUForeignVRAMMB int
GPUIgnoreProcs []string
GamePollInterval time.Duration
GameProcs []string `env:"GAME_PROCS"`
GPUForeignVRAMMB int `env:"GPU_FOREIGN_VRAM_MB"`
GPUIgnoreProcs []string `env:"GPU_IGNORE_PROCS"`
GamePollInterval time.Duration `env:"GAME_POLL_INTERVAL"`
WarmModel string
LogLevel slog.Level
LogJSON bool
LogFile string
WarmModel string `env:"WARM_MODEL"`
LogLevel slog.Level `env:"LOGLEVEL"`
LogJSON bool `env:"LOG_FORMAT"`
LogFile string `env:"LOG_FILE"`
}
// Defaults returns the configuration used when neither the environment nor