This is an automated email from the ASF dual-hosted git repository.

ChenSammi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 5d4972e025e HDDS-16209. KeyLifecycleService leaks inFlight entry when 
a task runs while shouldRun() is false (#11050)
5d4972e025e is described below

commit 5d4972e025e31dec8c991be5caeab4d64d123ee9
Author: Sergey Soldatov <[email protected]>
AuthorDate: Wed Aug 19 01:10:56 2026 -0700

    HDDS-16209. KeyLifecycleService leaks inFlight entry when a task runs while 
shouldRun() is false (#11050)
---
 .../ozone/om/service/KeyLifecycleService.java      |  5 +++
 .../ozone/om/service/TestKeyLifecycleService.java  | 40 ++++++++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/KeyLifecycleService.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/KeyLifecycleService.java
index c36097fd4d3..09289826594 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/KeyLifecycleService.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/KeyLifecycleService.java
@@ -466,6 +466,11 @@ public BackgroundTaskResult call() {
         }
 
         onSuccess(bucketKey);
+      } else {
+        // The task was registered in inFlight when scheduled, but the service 
got suspended/disabled
+        // or lost leadership before the task ran. Clear the registration, 
otherwise this bucket is
+        // skipped as "already running" in every following getTasks() cycle.
+        inFlight.remove(bucketKey);
       }
 
       // By design, no one cares about the results of this call back.
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestKeyLifecycleService.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestKeyLifecycleService.java
index 012123680f6..3f2a93c20c5 100644
--- 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestKeyLifecycleService.java
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestKeyLifecycleService.java
@@ -92,6 +92,8 @@
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList;
 import org.apache.hadoop.hdds.server.ServerUtils;
+import org.apache.hadoop.hdds.utils.BackgroundTask;
+import org.apache.hadoop.hdds.utils.BackgroundTaskQueue;
 import org.apache.hadoop.hdds.utils.db.DBConfigFromFile;
 import org.apache.hadoop.hdds.utils.db.RocksDatabaseException;
 import org.apache.hadoop.hdds.utils.db.Table;
@@ -529,6 +531,44 @@ void testBucketScanResume(BucketLayout bucketLayout, 
boolean createPrefix) throw
       deleteLifecyclePolicy(volumeName, bucketName);
     }
 
+    @Test
+    void testInFlightClearedWhenTaskSkipsRun() throws Exception {
+      final String volumeName = getTestName();
+      final String bucketName = uniqueObjectName("bucket");
+
+      keyLifecycleService.suspend();
+      createVolumeAndBucket(volumeName, bucketName, BucketLayout.OBJECT_STORE,
+          UserGroupInformation.getCurrentUser().getShortUserName());
+      ZonedDateTime date = 
ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(EXPIRE_SECONDS);
+      createLifecyclePolicy(volumeName, bucketName, BucketLayout.OBJECT_STORE, 
"key", null, date.toString(), true);
+      String bucketKey = metadataManager.getBucketKey(volumeName, bucketName);
+
+      try {
+        // Schedule the task manually. The service's own scheduler may win the 
registration and run
+        // the task to completion; in that case getTasks() returns nothing, so 
retry until this
+        // thread holds the scheduled task.
+        keyLifecycleService.resume();
+        BackgroundTaskQueue queue = keyLifecycleService.getTasks();
+        for (int i = 0; queue.isEmpty() && i < 200; i++) {
+          Thread.sleep(WAIT_CHECK_INTERVAL);
+          queue = keyLifecycleService.getTasks();
+        }
+        assertFalse(queue.isEmpty());
+
+        // Suspend before the scheduled task executes, then run it: call() 
skips the scan because
+        // shouldRun() is false, but must still clear the in-flight 
registration, otherwise the
+        // bucket is never scheduled again.
+        keyLifecycleService.suspend();
+        for (BackgroundTask task = queue.poll(); task != null; task = 
queue.poll()) {
+          task.call();
+        }
+        
assertFalse(keyLifecycleService.status().getRunningBucketsList().contains(bucketKey));
+      } finally {
+        keyLifecycleService.resume();
+        deleteLifecyclePolicy(volumeName, bucketName);
+      }
+    }
+
     @ParameterizedTest
     @MethodSource("parameters1")
     void testBucketScanWithScanEndTime(BucketLayout bucketLayout, boolean 
createPrefix) throws IOException,


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

Reply via email to