gpulock

package
v0.21.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package gpulock is the READ-ONLY Go view of the single-slot GPU lock owned by the Node render runners (render/gpu-lock.mjs). The 8GB GPU is shared between llama-swap (the VLM/text tiers) and ComfyUI/Chatterbox (the generation jobs); the runners serialize GPU-heavy work through one lock DIRECTORY (mkdir is atomic) holding a meta.json {pid, startedAt}.

LO-1 evidence: while a generation job held that lock, llama-swap could not (re)load the vision model, so EVERY vision call 5xx'd and deferred to the expensive cloud model (295 of the 337 all-time defers landed inside one such hour). This package lets the pipeline SEE the lock before burning a doomed HTTP call: resolve the same path the runners use, report held/not-held plus holder age, and wait (bounded) for the slot to free.

Invariants:

  • Read-only: this package NEVER creates, reclaims, or removes the lock — acquisition/stale-reclaim stay with the runners (gpu-lock.mjs owns them).
  • Same staleness rule as gpu-lock.mjs isStale(): missing/unreadable meta => stale; a recorded holder pid that is dead => stale; older than the 1h TTL (the no-pid fallback + pid-recycle backstop) => stale. Stale == not held.

Index

Constants

View Source
const DefaultLockName = "local-offload-gpu.lock"

DefaultLockName is the basename of the shared lock dir under the OS temp dir, matching defaultLockPath() in render/gpu-lock.mjs.

View Source
const DefaultTTL = time.Hour

DefaultTTL mirrors DEFAULT_TTL_MS in render/gpu-lock.mjs (1h — a real video generation can take many minutes; the TTL is only the fallback when the holder pid is unknown, and the backstop against pid recycling).

Variables

This section is empty.

Functions

func Path

func Path(override string) string

Path resolves the shared GPU lock directory exactly the way the Node render runners do (gpu-lock.mjs defaultLockPath): explicit override first (the gpu_lock_path config field — the pipeline also threads it to the runners as the GPU_LOCK env so both sides always contend on ONE path), then the GPU_LOCK env, then <os-tmpdir>/local-offload-gpu.lock. Note the default is TMPDIR- relative (per the .mjs), NOT exe-dir-relative like the render script paths.

Types

type Info

type Info struct {
	// Held is true when the lock dir exists AND its meta is not stale.
	Held bool
	// Age is how long the current holder has held the lock (time since the
	// meta.json mtime — the same clock gpu-lock.mjs uses). Zero when not held.
	Age time.Duration
	// PID is the recorded holder pid (0 when unknown / not held).
	PID int
}

Info is one point-in-time inspection of the lock.

func Inspect

func Inspect(lockPath string) Info

Inspect reports whether the lock at lockPath is currently held, using the same staleness rule as gpu-lock.mjs with the default 1h TTL. A stale lock (dead holder / no meta / over-TTL) reports NOT held — reclaiming it is the runners' job, never ours.

func WaitFree

func WaitFree(ctx context.Context, lockPath string, wait, poll time.Duration) Info

WaitFree polls the lock every poll (min bound 1ms; the pipeline passes 2s) until it is free or wait has elapsed (or ctx is done), returning the FINAL inspection: Held=false means the slot freed (proceed); Held=true means the caller should defer, with Age available for the defer reason.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL