feat(engine): guard one engine per project per machine
Adds a per-machine singleton lock that engages in
ProjectEngineManager.createAndStart() before any engine subsystems
spin up. Two fn dashboard processes can no longer run engines for the
same project on the same host — previously they would share .fusion/
state and corrupt worktrees / task rows for in-process projects.
The guard combines two independent checks:
- A proper-lockfile file at <project>/.fusion/engine.lock with
stale-lock recovery (auto-released on process death).
- A loopback listener on a hashed per-project address — UDS on
POSIX, named pipe on Windows. Stale UDS files are probed and
unlinked before a retry bind.
Failures raise EngineAlreadyRunningError. Both guards are released
from stopAll() and pauseProject(); a release on engine.start()
failure lets retries re-acquire cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
20
.changeset/engine-singleton-lock.md
Normal file
20
.changeset/engine-singleton-lock.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
"@fusion/engine": minor
|
||||
---
|
||||
|
||||
feat(engine): guard one engine per project per machine
|
||||
|
||||
Adds a per-machine singleton lock that engages before each engine
|
||||
starts, preventing two `fn` dashboard processes from running engines
|
||||
for the same project on the same host (a scenario that previously
|
||||
caused worktree corruption and task-state races for in-process
|
||||
projects).
|
||||
|
||||
The guard combines two independent checks:
|
||||
- A `proper-lockfile`-backed file at `<project>/.fusion/engine.lock`
|
||||
with stale-lock recovery.
|
||||
- A loopback listener (UDS on POSIX, named pipe on Windows) on a
|
||||
hashed per-project address.
|
||||
|
||||
Failures throw `EngineAlreadyRunningError`; both guards are released
|
||||
on `stopAll()` / `pauseProject()`.
|
||||
Reference in New Issue
Block a user