Jackie-Jiang commented on code in PR #19735:
URL: https://github.com/apache/pinot/pull/19735#discussion_r4200510283


##########
pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/lineage/DefaultLineageManager.java:
##########
@@ -107,31 +122,38 @@ public void updateLineageForRetention(TableConfig 
tableConfig, SegmentLineage li
             segmentsToDelete.addAll(sourceSegments);
           }
         }
-      } else if (lineageEntry.getState() == LineageEntryState.REVERTED || (
-          lineageEntry.getState() == LineageEntryState.IN_PROGRESS && 
lineageEntry.getTimestamp()
-              < System.currentTimeMillis() - lineageCleanupRetentionMs)) {
+      } else if (isZombieEntryEligibleForCleanup(lineageEntry, 
lineageCleanupThresholdMs)) {

Review Comment:
   [P1] Retire obsolete shared destination references independently of the 
grace period.
   
   For a recent `REVERTED A→B` followed by `COMPLETED A→B`, this condition 
retains the reverted entry. 
`SegmentLineageUtils.filterSegmentsBasedOnLineageInPlace`, used by the broker 
preselector, then excludes `B` for the reverted entry and `A` for the completed 
entry, so neither is routable despite preserving `B` physically.
   
   The protection can also disappear across passes: with APPEND defaults, a 
pass after four hours deletes `A`; the next pass removes the completed entry 
because `A` is absent; once the reverted entry reaches 24 hours, `B` is 
unprotected and is deleted. Could we prune/retire obsolete shared references 
independently of zombie retention, and add a multi-pass regression that checks 
broker routing as well as segment preservation?



##########
pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/PinotHelixResourceManager.java:
##########
@@ -4803,16 +4922,35 @@ public void revertReplaceSegments(String 
tableNameWithType, String segmentLineag
         TableConfig tableConfig = 
ZKMetadataProvider.getTableConfig(_propertyStore, tableNameWithType);
         Map<String, String> customMap =
             revertReplaceSegmentsRequest == null ? null : 
revertReplaceSegmentsRequest.getCustomMap();
-        if (writeLineageEntryWithLock(tableConfig, segmentLineageEntryId, 
lineageEntryToUpdate, lineageEntry,
-            _propertyStore, LineageUpdateType.REVERT, customMap)) {
+        int writtenLineageVersion = writeLineageEntryWithLock(tableConfig, 
segmentLineageEntryId,

Review Comment:
   [P1] Retry lifecycle validation when the cleanup fence advances.
   
   The new fence still permits this interleaving: revert validates that source 
`A` of `COMPLETED A→B` is ONLINE; retention cleanup removes `A` and bumps the 
lineage version; `writeLineageEntryWithLock()` re-fetches the newer version, 
sees unchanged entry contents, and commits `REVERTED`. Routing then returns to 
missing `A`, and proactive revert cleanup can also delete `B`. Completion has 
the analogous gap for expired `IN_PROGRESS` destinations.
   
   This race existed before the PR, but the new version bump does not close it 
because the helper retries only the write. Could we bind it to the version used 
for validation and retry the outer operation on a version change, so the 
segment-existence checks run again?



##########
pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/retention/RetentionManager.java:
##########
@@ -543,9 +553,15 @@ private void 
manageSegmentLineageCleanupForTable(TableConfig tableConfig) {
     }
     // Delete segments based on the segment lineage
     if (!segmentsToDelete.isEmpty()) {
-      
_pinotHelixResourceManager.deleteSegmentsForLineageCleanup(tableNameWithType, 
segmentsToDelete);
-      LOGGER.info("Finished cleaning up segment lineage for table: {} in {}ms, 
deleted segments: {}",
-          tableNameWithType, (System.currentTimeMillis() - cleanupStartTime), 
segmentsToDelete);
+      PinotResourceManagerResponse cleanupResponse = 
_pinotHelixResourceManager.deleteSegmentsForLineageCleanup(
+          tableNameWithType, segmentsToDelete, cleanupLineageVersion[0]);
+      if (cleanupResponse.isSuccessful()) {
+        LOGGER.info("Finished cleaning up segment lineage for table: {} in 
{}ms, deleted segments: {}",
+            tableNameWithType, (System.currentTimeMillis() - 
cleanupStartTime), segmentsToDelete);
+      } else {

Review Comment:
   [P2] Preserve orphan cleanup intent when the version check rejects deletion.
   
   For an expired zombie destination absent from IdealState but still present 
in segment metadata, `DefaultLineageManager` removes its lineage entry and 
returns the orphan as a deletion candidate. That removal is committed before 
this call. If an unrelated replacement updates lineage in between, the new 
version check rejects deletion and this branch only logs it. The next pass 
cannot rediscover the candidate because its lineage entry is gone.
   
   OFFLINE REFRESH tables skip ordinary retention, so the metadata and 
deep-store data can remain indefinitely. Could we keep durable cleanup intent 
until deletion succeeds, with a regression that interleaves an unrelated 
lineage update and verifies a later pass still reaps the orphan?



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