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

   ### SUMMARY
   
   Fixes SC-115615 — two retention-interaction races in the versioning backend, 
both confirmed by two independent review panels (10-lens capstone + Codex 
capstone Highs #4/#5), sharing test scaffolding. Both scale with 
`SUPERSET_VERSION_HISTORY_RETENTION_DAYS` set and capture on — the 
fleet-enablement configuration.
   
   **1. Freshly captured baselines could immediately expire** 
(`superset/versioning/baseline/insertion.py`). The baseline transaction's 
`issued_at` was sourced from the entity's historical `changed_on`, but the 
retention prune keys on `issued_at` — and the baseline's shadow row is closed 
by the same flush's real edit, so the prune's live-row preservation rule 
doesn't protect it. Capture a baseline for an entity last edited outside the 
retention window and the very next prune deleted it: the entity's pre-edit 
history gone permanently. The baseline is now stamped with **capture time on 
one clock** (naive-UTC, matching Continuum's storage and the prune's cutoff 
derivation; the old `sa.func.now()` fallback mixed in the DB server's local 
clock). Panel chronology is unaffected — baseline-first ordering is by 
`operation_type`, not `issued_at` — and attribution stays with the 
pre-versioning author via `user_id`.
   
   **2. Snapshot fetch by OFFSET shifted under a concurrent prune** 
(`superset/versioning/queries.py`). `get_version` resolved the target to a 
stable `transaction_id`, threw it away, and re-fetched by positional OFFSET — a 
prune committing in between shifts the offset and silently surfaces a 
**different version's snapshot under the requested version uuid**, on the 
preview/restore read path. The fetch now addresses the row by the resolved 
`transaction_id` (identity filter kept, so a transaction id recycled on another 
entity can never match). The restore command already addressed by 
`transaction_id`; this closes the read side.
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   N/A — backend correctness.
   
   ### TESTING INSTRUCTIONS
   
   ```bash
   python -m pytest tests/unit_tests/versioning -q   # 149 passed (4 new in 
test_retention_races.py)
   ```
   
   The new tests drive the **real** production functions against a shared 
Continuum-shaped in-memory store. Reverted-fix control (both fixed files 
checked out from the base commit): exactly the two race tests flip — 
`test_baseline_survives_a_full_retention_window_from_capture` (baseline expires 
immediately) and `test_get_version_returns_resolved_tx_after_concurrent_prune` 
(OFFSET returns the successor's snapshot) — while the attribution/shadow-shape 
and no-prune controls stay green in both states (`2 failed, 2 passed`).
   
   ### ADDITIONAL INFORMATION
   
   - [x] Has associated issue: SC-115615 (refs apache/superset#41551 capstone; 
sc-111918 rollout)
   - [x] Required feature flags: `ENABLE_VERSIONING_CAPTURE` (+ retention 
configured, for the code paths involved)
   - [ ] Changes UI
   - [ ] Includes DB Migration (follow approval process in 
[SIP-59](https://github.com/apache/superset/issues/13351))
   - [ ] Introduces new feature or API
   - [ ] Removes existing feature or API
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   
   https://claude.ai/code/session_01JRLEJS4mUqKBoPjSjviKUW
   


-- 
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