Proposal, design, spec, and tasks for the per-installation exclusive instance lock. 15/16 tasks complete; only manual real-environment verification (5.4) remains, with semantics covered by unit tests in test_app.py and test_instance_lock.py. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.1 KiB
ADDED Requirements
Requirement: Host Agent acquires an exclusive local instance lock before any control-plane side effect
The Host Agent SHALL acquire an exclusive, non-blocking lock scoped to its configured identity_path state directory as the first action of application startup, before resolving host identity, enrolling any device, or contacting the control plane.
Scenario: Lock acquired on normal startup
- WHEN a Host Agent starts and no other process holds the lock for its
identity_pathstate directory - THEN it acquires the lock and proceeds to identity resolution, device enrollment, and the heartbeat/claim loops as before
Scenario: Duplicate instance is rejected before any network call
- WHEN a second Host Agent process starts against the same
identity_pathstate directory while a first process is still running - THEN the second process fails to acquire the lock and exits without resolving host identity, enrolling any device, or otherwise contacting the control plane
Requirement: Duplicate-instance rejection is immediate and clearly identified
The Host Agent SHALL fail immediately, without waiting or retrying, when the instance lock is already held, and SHALL log an error that identifies the failure as a duplicate-instance conflict distinct from other startup failures.
Scenario: Operator sees an actionable error
- WHEN a duplicate Host Agent instance fails to acquire the lock
- THEN the logged error names the lock file location and identifies the cause as another instance already running, rather than a generic or unrelated startup failure
Requirement: The instance lock releases without manual intervention after any process exit
The Host Agent SHALL release its instance lock when its process exits for any reason, including graceful shutdown, an unhandled exception, or a forced kill, without requiring any manual cleanup step before a subsequent instance can start.
Scenario: Lock is released after graceful shutdown
- WHEN a running Host Agent instance completes its graceful shutdown sequence
- THEN a new Host Agent instance started afterward against the same
identity_pathstate directory successfully acquires the lock
Scenario: Lock is released after an unclean process exit
- WHEN a running Host Agent instance is terminated forcefully (e.g. killed) without running its shutdown sequence
- THEN a new Host Agent instance started afterward against the same
identity_pathstate directory successfully acquires the lock without any manual lock file cleanup
Requirement: Instance lock scope is per identity, not machine-global
The instance lock SHALL be scoped to the Host Agent's configured identity_path state directory, such that two Host Agent processes configured with different identity_path values SHALL be able to run concurrently on the same machine.
Scenario: Independent identities do not contend
- WHEN two Host Agent processes start on the same machine with different
identity_pathstate directories - THEN both acquire their respective locks and run concurrently without either being rejected