dotCMS / dotCMS/core

OSGi extra-packages: return 409 on skipped manual write + handle it in the UI (follow-up to #36434)

Open
#36,537 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

dotCMS : OSGi OKR : Customer Support Team : Maintenance
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Follow-up to #36434 / PR #36503.

Background

PR #36503 (High #2 fix) wrapped the manual PUT /api/v1/osgi/extra-packages writer (OSGIUtil.writeOsgiExtras, incl. RESET) in the cluster-wide OSGI_RESTART_LOCK_KEY shedlock, so it can no longer race the upload pipeline's read-merge-write of osgi-extra.conf.

The backend review noted (and it's correct) that ClusterLockManagerImpl.tryLock (ShedLock's executeWithLock) is a try-lock: if the lock is already held (e.g. an upload merge is in progress on any node), the callback is silently skipped — no exception. As a result, when a manual edit races an in-progress upload merge:

  • the manual write/delete is skipped,
  • no exception propagates,
  • OSGIResource.modifyExtraPackages still returns 200 "OSGI Extra Packages Saved" — an optimistic success for a change that was not actually persisted.

This is a narrow, non-blocking window (the shared file itself never diverges; only this specific admin action can be silently superseded), so it was intentionally left out of #36503. This issue tracks closing it properly.

Why it needs both backend and frontend changes

Returning a 409 Conflict from the backend is the natural fix, but the UI would swallow it silently as-is:

  • DotHttpErrorManagerService (core-web/libs/data-access/src/lib/dot-http-error-manager/dot-http-error-manager.service.ts) only maps NOT_FOUND, UNAUTHORIZED, FORBIDDEN, SERVER_ERROR, BAD_REQUEST, NO_CONTENT. There is no CONFLICT/409 handler, so callErrorHandler(409) returns false and shows no toast.
  • dot-plugins-extra-packages.component.ts save() / #doReset() only call httpErrorManager.handle(error) in catchError with no fallback message, so a 409 leaves the dialog open with zero user feedback — worse UX than the current optimistic 200.

So this must ship as a paired backend + frontend change.

Proposed work

Backend (dotCMS)
  • ClusterLockManager/writeOsgiExtras: surface whether the locked callback actually executed (ShedLock LockAssert / a wasExecuted boolean from the task result) instead of returning silently.
  • OSGIResource.modifyExtraPackages: when the write was skipped because the lock was held, return 409 Conflict with a clear message (e.g. "An OSGi deployment is in progress; please retry.") instead of 200. Update the @Operation/@ApiResponse docs + regenerate openapi.yaml.
Frontend (core-web)
  • Add a CONFLICT (409) handler to DotHttpErrorManagerService (or handle 409 explicitly in the extra-packages component) that shows a retriable-conflict message, so the admin sees "deployment in progress, retry" rather than nothing.
  • i18n key for the message.
  • Jest coverage: 409 path shows the message and keeps the dialog open (does not close as success).

Acceptance criteria

  • A manual extra-packages save/RESET that loses the lock returns 409 and the UI shows a clear, retriable message; the dialog stays open and is not reported as saved.
  • A successful save still returns 200 and closes the dialog as today.

Affected versions

Notes

  • Non-blocking for #36503 — that PR's lock fix is correct; this only replaces the optimistic 200 on the (now-serialized) contention path with an honest 409 + matching UI feedback.

Refs: #36434, #36503

External Links

https://dotcms.freshdesk.com/a/tickets/37894

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with ClusterLockManager, OSGIUtil.writeOsgiExtras, and OSGIResource.modifyExtraPackages to trace how a skipped lock callback is reported and how the response is documented. Then inspect core-web/libs/data-access/src/lib/dot-http-error-manager/dot-http-error-manager.service.ts and dot-plugins-extra-packages.component.ts, along with the related Jest tests. Done means lock contention returns 409 with updated OpenAPI documentation, the UI shows a retriable message and keeps the dialog open, and successful saves still return 200 and close it.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, typescript
Domain
api, backend, documentation, frontend, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.