msyavuz opened a new pull request, #43583:
URL: https://github.com/apache/superset/pull/43583

   ### SUMMARY
   
   Editing the same dataset in two tabs can silently erase a change you already 
saved. Tab 1 saves a new description; Tab 2 — still holding the pre-edit form — 
changes only the cache timeout and saves. `DatasourceModal` PUTs a *full* 
object rebuilt from its in-memory snapshot, and `PUT /api/v1/dataset/<pk>` 
applied it unconditionally, so Tab 2's save reverted the description. No 
warning in either tab.
   
   The dataset GET already returns an `ETag` (the live version uuid, from the 
existing versioning infra). This wires it up as an optimistic-concurrency token 
rather than a reporting-only header:
   
   - The modal captures the `ETag` of the read its form was seeded from and 
replays it as `If-Match` on save.
   - `PUT /api/v1/dataset/<pk>` compares it against the live version uuid it 
*already* computes pre-update (`old_info`, no extra query) and returns **412** 
with the current `ETag` on mismatch.
   - The losing tab gets a "Dataset changed since you opened it" dialog instead 
of a silent overwrite.
   
   Deliberately conservative: a PUT with no `If-Match` behaves exactly as 
before, and the check is skipped when there is no validator to compare against 
(`ENABLE_VERSIONING_CAPTURE` off, or no version rows yet) so those deployments 
aren't blocked from saving. The `raise_for_stale_write` helper lives in 
`superset/versioning/etag.py` so charts/dashboards can adopt the same guard 
later.
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   N/A — the visible change is a new conflict dialog on the losing save, 
reproducible via the steps below.
   
   ### TESTING INSTRUCTIONS
   
   1. Open the same dataset's edit modal in two browser tabs.
   2. Tab 1: change the Description, Save. Confirm it persisted.
   3. Tab 2: change only the cache timeout, Save.
   4. Before: Tab 2 succeeds and the Description silently reverts. After: Tab 2 
is refused with "Dataset changed since you opened it", and Tab 1's Description 
survives.
   5. Reopen the dataset in Tab 2, reapply the timeout, Save — succeeds.
   
   Automated: \`pytest tests/unit_tests/versioning/test_etag.py 
tests/unit_tests/datasets/api_tests.py\` and \`npm run test -- 
DatasourceModal.test.tsx\`.
   
   ### ADDITIONAL INFORMATION
   - [ ] Has associated issue: No
   - [ ] Required feature flags: None. The guard is inert (falls back to the 
old unconditional write) when \`ENABLE_VERSIONING_CAPTURE\` is off.
   - [x] Changes UI — new conflict dialog on a rejected save; no layout changes.
   - [ ] Includes DB Migration: No
   - [ ] Introduces new feature or API: No new endpoint. \`PUT 
/api/v1/dataset/<pk>\` gains an optional \`If-Match\` request header and a 412 
response, documented in the OpenAPI spec; existing clients are unaffected.
   - [ ] Removes existing feature or API: No


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to