maintenance portlet | Implement fix assets and clean orphan assets polling APIs #35191#35232
maintenance portlet | Implement fix assets and clean orphan assets polling APIs #35191#35232hassandotcms wants to merge 21 commits intomainfrom
Conversation
…s, and delete pushed assets #35191 Add three new endpoints to MaintenanceResource: - POST /_searchAndReplace: database-wide find/replace across content tables - DELETE /_oldVersions: drop versionable objects older than a given date - DELETE /_pushedAssets: clear all push publishing history Includes Validated forms, @Value.Immutable response views, full Swagger annotations, and SecurityLogger entries for all destructive operations.
…ions, and pushed assets #35191 Tests cover: - _searchAndReplace: admin success, non-admin rejection, null/empty form validation, empty replaceString allowed - _oldVersions: admin success, non-admin rejection, missing date, invalid date formats - _pushedAssets: admin success, non-admin rejection
|
Claude finished @hassandotcms's task in 4m 21s —— View job PR Review
Issues Found1.
2.
3. Incomplete double-checked locking in
MaintenanceJobHelper local = jobHelper;
if (local == null) {
local = CDIUtils.getBean(...).orElseThrow(...);
jobHelper = local; // no inner null check
}is missing the inner null check from the standard DCL pattern. Two threads can both see synchronized (this) {
local = jobHelper;
if (local == null) {
jobHelper = local = CDIUtils.getBean(...).orElseThrow(...);
}
}4.
5.
6.
7.
8.
Not Issues
|
|
Rollback safety analysis complete. Safe To Rollback. Label applied. |
642aeae to
cf2de86
Compare
…ts with polling #35191 Add four new endpoints to MaintenanceResource: - POST /_fixAssets: run all FixTask classes to fix DB inconsistencies - GET /_fixAssets: poll fix assets task results - POST /_cleanAssets: start background thread to clean orphan asset dirs - GET /_cleanAssets: poll clean assets progress status POST /_cleanAssets returns 409 Conflict if already running. Includes @Value.Immutable CleanAssetsStatusView, full Swagger annotations, and integration tests.
cf2de86 to
054bbe1
Compare
…s, and delete pushed assets #35191 Add three new endpoints to MaintenanceResource: - POST /_searchAndReplace: database-wide find/replace across content tables - DELETE /_oldVersions: drop versionable objects older than a given date - DELETE /_pushedAssets: clear all push publishing history Includes Validated forms, @Value.Immutable response views, full Swagger annotations, and SecurityLogger entries for all destructive operations.
…ions, and pushed assets #35191 Tests cover: - _searchAndReplace: admin success, non-admin rejection, null/empty form validation, empty replaceString allowed - _oldVersions: admin success, non-admin rejection, missing date, invalid date formats - _pushedAssets: admin success, non-admin rejection
…ndant checkValid, log searchString #35199
…tring from SecurityLogger #35199
…ilure in searchAndReplace #35199
…tenance-search-replace-old-versions-pushed-assets
…sets' into 35200-maintenance-fix-assets-clean-assets
…tenance-fix-assets-clean-assets
…assets endpoints #35200 Resolves PR #35232 review feedback: - CleanAssetsThread: volatile fields for cross-thread visibility; synchronized getInstance(); new atomic startCleanProcess() that claims running state before super.start() so callers can't observe running=false immediately after POST. - MaintenanceResource.startCleanAssets: uses startCleanProcess() to eliminate the TOCTOU race that could double-start the thread and throw IllegalThreadStateException. - MaintenanceResource.startFixAssets: AtomicBoolean guard returns 409 if already in flight; defensive copy of FixTasksExecutor's singleton result list prevents ConcurrentModificationException when a GET overlaps the POST. - MaintenanceResource: SecurityLogger audit entries on both POST endpoints, matching the existing pattern used by searchAndReplace/dropOldVersions/deletePushedAssets. - getFixAssetsProgress: clarified javadoc/Swagger that POST is synchronous and GET returns last-run results (page-reload scenarios), not live progress. - Integration tests: assertTrue(status.running()) on cleanAssets start; concurrent-start 409 tests for both cleanAssets and fixAssets.
…tenance-fix-assets-clean-assets
| description = "Conflict - fix assets process is already running", | ||
| content = @Content(mediaType = "application/json")) | ||
| }) | ||
| @POST |
There was a problem hiding this comment.
How about naming them like :
maintenance/assets/fix
maintenance/assets/clean
or
maintenance/assets/_fix
maintenance/assets/_clean
To please some folks
There was a problem hiding this comment.
maintenance/assets/_fix
maintenance/assets/_clean
seems better, consistent with other apis in this file.
|
|
||
| final User user = assertBackendUser(request, response).getUser(); | ||
|
|
||
| if (!FIX_ASSETS_RUNNING.compareAndSet(false, true)) { |
There was a problem hiding this comment.
I'm afraid this does not guarantee that the process might have been started on a different node
Perhaps you should use our Redis cache to make a lock
We also have a LockManager, which implements an identifier lock based
There was a problem hiding this comment.
hmm, valid point. fix in progress
| * @return | ||
| */ | ||
| public static CleanAssetsThread getInstance ( Boolean restartIfDied, boolean processBinary ) { | ||
| public static synchronized CleanAssetsThread getInstance ( Boolean restartIfDied, boolean processBinary ) { |
There was a problem hiding this comment.
This is an excellent opportunity to use our JobQueue rather than Threads that can be executed on different nodes simultaneously. Look at JobQueueManagerAPI
it works like a job queue managed by a single node. You can register a specialized JobProcessor to read from our job queue and handle an arbitrary task. Our Content Import API Works on top of that. It is intended to replace Quartz
There was a problem hiding this comment.
have a look at com/dotcms/rest/api/v1/content/dotimport/ContentImportResource.java
There was a problem hiding this comment.
done. using JobQueue now.
…erAPI #35200 Addresses review feedback from @fabrizzio-dotCMS on PR #35232: - Endpoint paths renamed from _fixAssets/_cleanAssets to assets/_fix and assets/_clean (nested-resource convention). - JVM-local AtomicBoolean replaced with cluster-aware ClusterLockManager (ShedLock/JDBC) around the check-and-create so two nodes cannot both pass the active-job guard in the same millisecond. - Fix-assets and clean-assets REST execution migrated to JobQueueManagerAPI via new @Queue processors; legacy CleanAssetsThread and FixTasksExecutor classes are untouched, so DWR/Quartz callers continue to work unchanged. New classes: MaintenanceJobHelper — creates jobs, enforces 409 semantics FixAssetsJobProcessor — runs FixTasksExecutor on the job worker CleanAssetsJobProcessor — runs CleanAssetsThread.run() on the job worker, bridges BasicProcessStatus to the progress tracker Removed (unused after the migration): AbstractCleanAssetsStatusView ResponseEntityCleanAssetsStatusView CleanAssetsThread.startCleanProcess() (dead helper) getLatestJob() switched from getCompletedJobs (ordered completed_at ASC — returned the oldest job) to getJobs (ordered created_at DESC — returns the most recent regardless of state). Integration tests reshaped to the job-queue shape: POST returns a jobId, tests poll JobQueueManagerAPI until the job reaches a terminal state, and assert the persisted result metadata. Added an end-to-end test that plants a UUID-named orphan directory under the assets root and verifies clean-assets deletes it. Test method docs follow the project's "Given scenario / Expected result" convention.
…tenance-fix-assets-clean-assets
Summary
Add 4 new REST endpoints to
MaintenanceResource, replacing legacy DWR fix assets and clean assets operations with modern REST APIs for the Maintenance portlet Tools tab.New endpoints:
POST /api/v1/maintenance/_fixAssets— Runs all registered FixTask classes that check for and fix database inconsistencies. Executes synchronously and returns task results when complete.GET /api/v1/maintenance/_fixAssets— Polls current fix assets task results. Used by the UI to check progress while the process is running.POST /api/v1/maintenance/_cleanAssets— Starts a background thread that walks the assets directory structure, checks each directory against the contentlet database, and deletes orphan binary folders. Returns 409 Conflict if already running.GET /api/v1/maintenance/_cleanAssets— Polls clean assets background process status (totalFiles, currentFiles, deleted, running, status).Implementation details:
CleanAssetsStatusView(@Value.Immutable) with typed fields instead ofBeanUtils.describe()string mapPOST /_cleanAssetspreventsIllegalThreadStateExceptionfrom calling.start()on an already-running threadFixTasksExecutorresults returned asList<Map>(raw type from executor, cannot be typed further)ResponseEntityCleanAssetsStatusViewtyped wrapper for Swagger documentationTest plan
./mvnw verify -pl :dotcms-integration -Dcoreit.test.skip=false -Dit.test=MaintenanceResourceIntegrationTestPOST /_fixAssetsas admin returns 200 with task results or null entityGET /_fixAssetsreturns current task resultsPOST /_cleanAssetsstarts process and returns initial status withrunning: trueGET /_cleanAssetsreturns current status with totalFiles, currentFiles, deleted, running, status fieldsPOST /_cleanAssetswhile already running returns 409 ConflictCloses #35200, Closes #35202