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>
This commit is contained in:
+37
@@ -0,0 +1,37 @@
|
||||
## 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_path` state 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_path` state 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_path` state 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_path` state 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_path` state directories
|
||||
- **THEN** both acquire their respective locks and run concurrently without either being rejected
|
||||
Reference in New Issue
Block a user