feat(plugins): consolidate lifecycle lock ownership#85
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
📝 WalkthroughWalkthroughDynamic plugin registration no longer retains classloader references. Unregistration now preserves plugin-map state when registry removal fails. Dynamic job loading uses reference-counted, reclaimable per-definition lifecycle locks with expanded concurrency coverage. ChangesPlugin lifecycle infrastructure
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant DynamicJobLoaderService
participant LifecycleLockHolder
participant PluginRegistryService
Caller->>DynamicJobLoaderService: loadJob(definitionId)
DynamicJobLoaderService->>LifecycleLockHolder: acquire definition lock
DynamicJobLoaderService->>PluginRegistryService: registerDynamicPlugin(plugin)
PluginRegistryService-->>DynamicJobLoaderService: registration result
DynamicJobLoaderService->>LifecycleLockHolder: release reference
LifecycleLockHolder-->>DynamicJobLoaderService: remove unused holder
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
fr-batch-service/src/main/java/com/fronzec/frbatchservice/batchjobs/plugins/PluginRegistryService.java (1)
47-52: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winUpdate the Javadocs after removing registry classloader ownership.
The former field comment now documents the constructor,
@param classLoaderRefno longer exists, and unregister documentation still referencesclassloaderRefs. Update these to describe the new API and failure-preserving map behavior.As per coding guidelines, “Provide Javadoc comments for all public classes, interfaces, methods, and significant fields explaining their purpose, parameters, and return values.”
Also applies to: 185-185, 252-255
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@fr-batch-service/src/main/java/com/fronzec/frbatchservice/batchjobs/plugins/PluginRegistryService.java` around lines 47 - 52, Update the Javadocs in PluginRegistryService to match the API after registry classloader ownership was removed: move the former field description off the constructor, remove the obsolete `@param` classLoaderRef reference, and revise unregister documentation to describe the map’s failure-preserving behavior. Ensure all public methods and significant fields document their current purpose, parameters, and return values.Source: Coding guidelines
🧹 Nitpick comments (1)
fr-batch-service/src/test/java/com/fronzec/frbatchservice/batchjobs/plugins/loader/DynamicJobLoaderServiceTest.java (1)
479-507: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winWait until contenders join the holder before asserting exclusion.
Line 498 may execute before the second task starts, while Line 565 only proves one map entry exists—not that both queued callers incremented
users. Wait for the holder count to reach 2/3 before asserting and releasing the first caller.Also applies to: 545-576
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@fr-batch-service/src/test/java/com/fronzec/frbatchservice/batchjobs/plugins/loader/DynamicJobLoaderServiceTest.java` around lines 479 - 507, Update withDefinitionLock_sameIdExcludesConcurrentCallers and the analogous test around the shared lifecycle-lock assertions to await the lock holder’s users count reaching 2/3, confirming contenders have joined before asserting exclusion or releasing the first caller. Use the existing lifecycle-lock inspection helpers and retain the current cleanup and completion assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@fr-batch-service/src/main/java/com/fronzec/frbatchservice/batchjobs/plugins/loader/DynamicJobLoaderService.java`:
- Line 238: Track whether registration succeeded around
DynamicJobLoaderService’s pluginRegistryService.registerDynamicPlugin call, and
in the catch cleanup unregister the plugin before closing/removing its
classloader. If unregistering fails, preserve the classloader entry so the
registered plugin is not orphaned; only release the classloader after successful
rollback.
---
Outside diff comments:
In
`@fr-batch-service/src/main/java/com/fronzec/frbatchservice/batchjobs/plugins/PluginRegistryService.java`:
- Around line 47-52: Update the Javadocs in PluginRegistryService to match the
API after registry classloader ownership was removed: move the former field
description off the constructor, remove the obsolete `@param` classLoaderRef
reference, and revise unregister documentation to describe the map’s
failure-preserving behavior. Ensure all public methods and significant fields
document their current purpose, parameters, and return values.
---
Nitpick comments:
In
`@fr-batch-service/src/test/java/com/fronzec/frbatchservice/batchjobs/plugins/loader/DynamicJobLoaderServiceTest.java`:
- Around line 479-507: Update withDefinitionLock_sameIdExcludesConcurrentCallers
and the analogous test around the shared lifecycle-lock assertions to await the
lock holder’s users count reaching 2/3, confirming contenders have joined before
asserting exclusion or releasing the first caller. Use the existing
lifecycle-lock inspection helpers and retain the current cleanup and completion
assertions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4b7c684c-922f-4a7b-86a8-63568c84cf70
📒 Files selected for processing (4)
fr-batch-service/src/main/java/com/fronzec/frbatchservice/batchjobs/plugins/PluginRegistryService.javafr-batch-service/src/main/java/com/fronzec/frbatchservice/batchjobs/plugins/loader/DynamicJobLoaderService.javafr-batch-service/src/test/java/com/fronzec/frbatchservice/batchjobs/plugins/PluginRegistryServiceTest.javafr-batch-service/src/test/java/com/fronzec/frbatchservice/batchjobs/plugins/loader/DynamicJobLoaderServiceTest.java
bb83a1a to
b79178f
Compare
|
Addressed the first two CodeRabbit findings: late load failures now roll back registration before classloader cleanup, classloader ownership is retained if rollback unregister fails, and stale registry Javadocs were updated. Focused tests: 35 passed. Full module: 134 passed. The concurrency timing nitpick was intentionally not included in this update. |
Closes #86 ## Summary - Serialize load, unload, and reload transitions per plugin definition. - Hold one lifecycle lock across reload unload and replacement load. - Preserve deterministic failure state and allow explicit recovery from `FAILED`. ## Chain Context `main` <- #85 lifecycle ownership <- #87 lifecycle transitions (current) 📍 This is PR 2 of 2. It starts from PR #85's registry ownership and reference-counted lifecycle holder, and ends with full lifecycle serialization, deterministic reload failure semantics, and verified ownership release. ## Changes | File | Change | |------|--------| | `DynamicJobLoaderService.java` | Serialize public lifecycle transitions and keep reload within one critical section. | | `DynamicJobLoaderServiceTest.java` | Cover lifecycle exclusion, reload failure semantics, ownership release, and `FAILED` recovery. | ## Test Plan - [x] Focused: `mvn -f fr-batch-service/pom.xml -Dtest=DynamicJobLoaderServiceTest,PluginRegistryServiceTest test` - PASS, 40 tests, 0 failures/errors/skips. - [x] Full module: `mvn test -f fr-batch-service/pom.xml` - PASS, 139 tests, 0 failures/errors/skips. - [x] Package: `mvn -f fr-batch-service/pom.xml -DskipTests package` - BUILD SUCCESS. ## Exclusions - DELETE safety and filesystem/database deletion coordination. - Multi-instance or distributed lifecycle locking. - Special repair APIs or a broad lifecycle transaction redesign. - The declined CodeRabbit holder-user timing nitpick. - The base-only initial `LOADING` persistence warning, unchanged from PR #85. ## Review Boundary - Review impact: 161 additions and 12 deletions across two files. - Rollback is limited to the loader service and its test in this PR. - No AI attribution or `Co-Authored-By` trailers.

Closes #84
Summary
DynamicJobLoaderServiceand removes duplicate ownership fromPluginRegistryService.This is the first stacked slice of the plugin lifecycle integrity work. Full unload/reload transition serialization remains intentionally out of scope for this PR.
Type of Change
Changes
PluginRegistryService.javaJobRegistry.unregisterfails.DynamicJobLoaderService.javaPluginRegistryServiceTest.javaDynamicJobLoaderServiceTest.javaTest Plan
mvn test -f fr-batch-service/pom.xmlb79178f.Contributor Checklist
Closes #84.type:*label:type:feature.Co-Authored-Bytrailers.