Skip to content

feat(editor): prevent double-save and handle version conflicts#815

Open
jma wants to merge 1 commit into
rero:stagingfrom
jma:maj-fix-concurrency
Open

feat(editor): prevent double-save and handle version conflicts#815
jma wants to merge 1 commit into
rero:stagingfrom
jma:maj-fix-concurrency

Conversation

@jma

@jma jma commented Jun 10, 2026

Copy link
Copy Markdown
Contributor
  • Guard submit() against re-entry while save is in progress
  • Disable save button visually during save
  • Add getRecordWithEtag() to retrieve ETag header; getRecord() delegates to it
  • Send If-Match header on PUT for optimistic concurrency control
  • Show specific warning flash message on 409/412 (record modified, reload needed)
  • Preserve 409/412 status codes in RecordHandleErrorService
  • Remove polyfills.ts (no longer needed without Zone.js)

Co-Authored-By: Bertrand Zuchuat bertrand.zuchuat@rero.ch
Co-Authored-By: Johnny Mariéthoz johnny.mariethoz@rero.ch

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This PR introduces ETag-based optimistic concurrency control to the record editor while simultaneously configuring the ng-core-tester application to run in zoneless mode. The RecordService gains two new methods: getRecord (data-only wrapper) and an updated getRecordWithEtag (returning both data and ETag header). The update method now accepts an optional ETag to set the If-Match header for server-side conflict detection. The editor loads records with ETag, stores it in a signal, threads it through save operations, and handles HTTP 409/412 conflict responses by warning the user. HTTP error handling is extended to classify these conflict codes. The test app removes Zone.js polyfills from build config and adds i18n language/translation configuration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: preventing double-save and handling version conflicts through ETag-based optimistic concurrency control, which are the core functional improvements in this PR.
Description check ✅ Passed The description is directly related to the changeset, providing specific details about the implementation approach including guard against re-entry, ETag handling, If-Match headers, conflict status codes, and removal of polyfills.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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 `@projects/rero/ng-core/src/lib/record/service/record/record.service.ts`:
- Around line 169-172: The mapping step currently casts response.body as T
without handling null; update the pipe map so it guards against
HttpResponse<T>.body being null by checking response.body and either (a)
returning a safe default (e.g., an empty object cast to T) for the "data" field
or (b) throwing a clear error that will be handled by _handleError; modify the
map that produces ({ data: response.body as T, etag: ... }) to first test
response.body and act accordingly so downstream code using the resulting data
cannot receive null unexpectedly.
- Around line 218-221: The If-Match header is only set when etag is truthy, so
empty-string ETag values are skipped; update the logic in RecordService.update
(the block that builds HttpHeaders where headers is set and checked with if
(etag)) to check for null/undefined instead (e.g., if (etag != null) or explicit
!== null/!== undefined) so an empty-string ETag is sent to the server and
optimistic concurrency works per RFC 9110.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d7ecd4b3-ce29-4854-ac63-5ab275947033

📥 Commits

Reviewing files that changed from the base of the PR and between 7eeff59 and 0033841.

📒 Files selected for processing (8)
  • angular.json
  • projects/ng-core-tester/src/environments/environment.ts
  • projects/ng-core-tester/src/polyfills.ts
  • projects/ng-core-tester/tsconfig.app.json
  • projects/rero/ng-core/src/lib/record/editor/component/editor/editor.component.html
  • projects/rero/ng-core/src/lib/record/editor/component/editor/editor.component.ts
  • projects/rero/ng-core/src/lib/record/service/record-handle-error/record-handle-error.service.ts
  • projects/rero/ng-core/src/lib/record/service/record/record.service.ts
💤 Files with no reviewable changes (3)
  • projects/ng-core-tester/src/polyfills.ts
  • angular.json
  • projects/ng-core-tester/src/environments/environment.ts

@jma jma force-pushed the maj-fix-concurrency branch from 0033841 to 6cccd21 Compare June 11, 2026 05:56
@Garfield-fr Garfield-fr self-requested a review June 11, 2026 08:10
@jma jma force-pushed the maj-fix-concurrency branch 2 times, most recently from fca60ad to d264d63 Compare June 11, 2026 09:13
- Guard submit() against re-entry while save is in progress
- Disable save button visually during save
- Add getRecordWithEtag() to retrieve ETag header; getRecord() delegates to it
- Send If-Match header on PUT for optimistic concurrency control
- Show specific warning flash message on 409/412 (record modified, reload needed)
- Preserve 409/412 status codes in RecordHandleErrorService
- Remove polyfills.ts (no longer needed without Zone.js)

Co-Authored-By: Johnny Mariéthoz <johnny.mariethoz@rero.ch>
@jma jma force-pushed the maj-fix-concurrency branch from d264d63 to 80c7dc2 Compare June 11, 2026 09:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants