Pre-flight Checks
Problem Description
Plugin lifecycle operations are not yet serialized end to end for a single definition. Concurrent load, unload, and reload transitions can interleave, and reload failure paths do not yet provide explicit transactional semantics for preserving the previous runtime or persisting a recoverable failure after teardown has completed.
Proposed Solution
Implement PR-C slice 2 using the reclaimable per-definition lifecycle lock introduced by PR #85:
- Use one per-definition lifecycle lock across load, unload, and reload.
- Keep the same lock for the entire reload operation, including forced unload and replacement load.
- If unload fails, abort replacement loading and preserve the previous runtime and persisted state.
- If unload completes but replacement loading fails, persist
FAILED and clean classloader/runtime ownership.
- Allow a normal explicit load to recover a definition from
FAILED.
- Add focused, deterministic concurrency and failure-path tests for these guarantees.
Acceptance Criteria
- Load, unload, and reload for the same definition cannot overlap; independent definitions remain able to progress independently.
- Reload retains one per-definition lock from entry through forced unload and replacement load completion or failure.
- An unload failure prevents replacement loading and leaves the prior runtime ownership and persisted lifecycle state intact.
- After a completed unload, a replacement-load failure persists
FAILED and leaves no stale classloader or runtime ownership.
- A later normal explicit load can transition a
FAILED definition through the existing load path and restore a valid loaded state.
- Lock references are released on every success and failure path so idle holders remain reclaimable.
Test Expectations
- Deterministic concurrency tests prove same-definition load, unload, and reload operations are serialized without timing-based sleeps.
- A reload test proves the lock remains held across forced unload and replacement load.
- Failure tests prove unload failure aborts replacement and preserves the previous runtime/state.
- Failure tests prove completed unload plus replacement failure persists
FAILED and cleans ownership.
- Recovery tests prove an explicit load recovers
FAILED.
- Existing plugin lifecycle tests continue to pass.
Affected Area
Plugin engine lifecycle coordination
Out of Scope
- DELETE safety.
- Distributed locking.
- A repair API.
- The initial
LOADING persistence follow-up.
Alternatives Considered
Using separate lock scopes for unload and replacement load was rejected because another lifecycle operation could interleave during reload. Distributed coordination was rejected because this slice addresses in-process lifecycle integrity only. Adding repair or DELETE behavior here was rejected to keep the stacked review boundary focused.
Additional Context
This is stacked PR 2 on PR #85. It consumes the lifecycle-lock and ownership infrastructure from that PR and intentionally limits this issue to end-to-end load/unload/reload transition integrity.
Pre-flight Checks
Problem Description
Plugin lifecycle operations are not yet serialized end to end for a single definition. Concurrent load, unload, and reload transitions can interleave, and reload failure paths do not yet provide explicit transactional semantics for preserving the previous runtime or persisting a recoverable failure after teardown has completed.
Proposed Solution
Implement PR-C slice 2 using the reclaimable per-definition lifecycle lock introduced by PR #85:
FAILEDand clean classloader/runtime ownership.FAILED.Acceptance Criteria
FAILEDand leaves no stale classloader or runtime ownership.FAILEDdefinition through the existing load path and restore a valid loaded state.Test Expectations
FAILEDand cleans ownership.FAILED.Affected Area
Plugin engine lifecycle coordination
Out of Scope
LOADINGpersistence follow-up.Alternatives Considered
Using separate lock scopes for unload and replacement load was rejected because another lifecycle operation could interleave during reload. Distributed coordination was rejected because this slice addresses in-process lifecycle integrity only. Adding repair or DELETE behavior here was rejected to keep the stacked review boundary focused.
Additional Context
This is stacked PR 2 on PR #85. It consumes the lifecycle-lock and ownership infrastructure from that PR and intentionally limits this issue to end-to-end load/unload/reload transition integrity.