EnxDev commented on code in PR #45029:
URL: https://github.com/apache/superset/pull/45029#discussion_r4200787034


##########
superset/tasks/version_history_retention.py:
##########
@@ -556,7 +683,23 @@ def prune_old_versions() -> dict[str, Any]:
         retention_days: int = _resolve_version_history_retention_days(
             configured, legacy_configured, seed=_version_history_retention_seed
         )
-        return _prune_old_versions_impl(retention_days)
+        try:
+            max_per_run: int | None = validate_retention_cap(
+                current_app.config.get(
+                    "VERSION_HISTORY_PRUNE_MAX_TRANSACTIONS_PER_RUN", 1000
+                ),
+                "VERSION_HISTORY_PRUNE_MAX_TRANSACTIONS_PER_RUN",
+            )
+        except ValueError:
+            logger.warning("version_history_retention: invalid prune cap; 
skipping")
+            
stats_logger_manager.instance.incr(f"{_METRIC_PREFIX}.skipped_invalid_cap")
+            return {"skipped_invalid_cap": 1}
+        dry_run: bool = 
current_app.config.get("VERSION_HISTORY_PRUNE_DRY_RUN", False)
+        if type(dry_run) is not bool:
+            raise ValueError("VERSION_HISTORY_PRUNE_DRY_RUN must be a bool")

Review Comment:
   A non-bool here raises into the broad `except` below, so it logs a full 
"task failed" traceback, bumps `.failed`, and returns `{"error": 1}`. That 
looks like a broken prune to whoever is on call, while a bad cap just above 
gets a clean `skipped_invalid_cap`.
   
   Worth handling it the same way, with a warning, a `skipped_invalid_dry_run` 
counter, and an early return?



##########
superset/tasks/version_history_retention.py:
##########
@@ -351,8 +352,46 @@ def _chunked(items: list[int], size: int) -> 
Iterator[list[int]]:
 _METRIC_PREFIX: str = "superset.versioning.retention"
 
 
+def _live_bearing_tables(tables: ShadowTables) -> list[sa.Table]:
+    """Return every shadow table that can anchor a live transaction."""
+    live_bearing_tables: list[sa.Table] = [*tables.parent, *tables.child]
+    if tables.m2m is not None:
+        live_bearing_tables.append(tables.m2m)
+    return live_bearing_tables
+
+
+def _count_prunable(cutoff: datetime, tables: ShadowTables) -> int:
+    """Count the full eligible transaction backlog without writing rows."""
+    total: int = 0
+    after_id: int = 0
+    live_bearing_tables: list[sa.Table] = _live_bearing_tables(tables)
+    conn: sa.engine.Connection
+    while True:
+        with db.engine.connect() as conn:
+            window: _PruneWindow = _resolve_prune_window(
+                conn, cutoff, live_bearing_tables, after_id, _MAX_PRUNE_BATCH
+            )
+        total += len(window.prunable)
+        if window.candidate_count < _MAX_PRUNE_BATCH:
+            return total
+        after_id = window.max_candidate_id
+
+
+def _probe_prunable(cutoff: datetime, tables: ShadowTables) -> tuple[int, 
bool]:
+    """Count one candidate window and say whether it covers the backlog."""
+    conn: sa.engine.Connection
+    with db.engine.connect() as conn:
+        window: _PruneWindow = _resolve_prune_window(
+            conn, cutoff, _live_bearing_tables(tables), 0, _MAX_PRUNE_BATCH

Review Comment:
   The probe always starts at id 0, but after a capped run everything below the 
last window is either already pruned or a live anchor. On an instance with a 
lot of charts and dashboards nobody has touched in 30+ days, the first 1000 
aged candidates end up being all anchors, so this reports 
`remaining_eligible=0` with `remaining_count_complete=False` on every run and 
the gauge never moves.
   
   Could `_add_prune_cap_stats` take the `after_id` the loop stopped at and 
probe from there? The remainder would then land on the real backlog. A unit 
test with a window of preserved ids ahead of the prunable ones would cover it.



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