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

yuqi1129 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new c4a9a856a2 [#13918] fix(doris): Reject adding auto-increment columns 
(#13919)
c4a9a856a2 is described below

commit c4a9a856a278f2b5199d845b6b102cffd0b4d584
Author: Qi Yu <[email protected]>
AuthorDate: Tue Oct 20 08:26:28 2026 +0800

    [#13918] fix(doris): Reject adding auto-increment columns (#13919)
    
    ### What changes were proposed in this pull request?
    
    - `DorisTableOperations`: reject an `AddColumn` change that sets
    `autoIncrement` with an `IllegalArgumentException`, instead of silently
    dropping the flag.
    - Document in `jdbc-doris-catalog.md` that auto-increment columns can
    only be defined at table creation.
    
    - Fix the CI failure in TMS by using consistent H2 epoch-millisecond
    calculations and deterministic claim-expiration fixtures.
    
    - Align Doris nested-column alteration rejections with the
    `TableCatalog.alterTable` contract by throwing
    `IllegalArgumentException`, consistent with the auto-increment
    rejection.
    
    ### Why are the changes needed?
    
    The add-column SQL ignored `isAutoIncrement()`, so the request succeeded
    without auto-increment. Emitting `AUTO_INCREMENT` is not an option:
    
    - Doris 2.1.5+ and 3.0.1+ reject it.
    - Earlier 2.1.x and 3.0.0 accept it, but never generate values for the
    added column (verified on Doris 2.1.0).
    
    The failing TMS CI job also exposed an H2 clock expression that can move
    backwards near a second boundary due to mixed timestamp precision. The
    H2-specific fix uses one high-precision timestamp.
    
    Fix: #13918
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes. Adding a column with `autoIncrement = true` to a Doris table now
    fails with `Doris does not support adding auto-increment column ...`,
    where it previously succeeded without auto-increment.
    
    H2-backed TMS claim leases also use consistent epoch milliseconds; no
    API or configuration changes.
    
    Rejected Doris nested-column alterations now return
    `IllegalArgumentException` (HTTP 400 rather than HTTP 501), as
    documented by the alter-table API.
    
    ### How was this patch tested?
    
    - New unit test
    
`TestDorisTableOperationsSqlGeneration.testAddAutoIncrementColumnIsRejected`.
    - `./gradlew :catalogs:catalog-jdbc-doris:test -PskipITs`
    - Checked the Doris behavior manually against
    `apache/doris:doris-all-in-one-2.1.0`.
    
    - TMS non-Docker suite: 23 tests passed; two expiration/reclamation
    tests each repeated 10 times.
    - Three time-zone boundary regression cases fail when the H2 clock fix
    is reverted.
    - TMS suite and Spotless rechecked on the final PR head.
    
    
    - Doris non-Docker suite: 103 tests passed, covering all five
    nested-column change paths and auto-increment rejection. Reverting the
    nested-column exception change makes all five regression cases fail.
    
    ---------
    
    Co-authored-by: yuqi <[email protected]>
---
 .../doris/operation/DorisTableOperations.java      | 19 ++++--
 .../TestDorisTableOperationsSqlGeneration.java     | 56 +++++++++++++---
 docs/jdbc-doris-catalog.md                         |  2 +
 .../h2/TableMaintenanceActionH2Provider.java       | 11 +++-
 .../maintenance/occupancy/TestOccupancyGate.java   |  6 +-
 .../storage/TableMaintenanceActionTestUtils.java   | 58 +++++++++++++++++
 .../h2/TestTableMaintenanceActionH2Provider.java   | 74 ++++++++++++++++++++++
 .../TestTableMaintenanceActionMetaService.java     | 11 ++--
 8 files changed, 214 insertions(+), 23 deletions(-)

diff --git 
a/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/operation/DorisTableOperations.java
 
b/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/operation/DorisTableOperations.java
index ef0ce30e62..a7d3bcf002 100644
--- 
a/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/operation/DorisTableOperations.java
+++ 
b/catalogs/catalog-jdbc-doris/src/main/java/org/apache/gravitino/catalog/doris/operation/DorisTableOperations.java
@@ -1002,7 +1002,7 @@ public class DorisTableOperations extends 
JdbcTableOperations {
       TableChange.UpdateColumnComment updateColumnComment) {
     String newComment = updateColumnComment.getNewComment();
     if (updateColumnComment.fieldName().length > 1) {
-      throw new UnsupportedOperationException("Doris does not support nested 
column names.");
+      throw new IllegalArgumentException("Doris does not support nested column 
names.");
     }
     String col = updateColumnComment.fieldName()[0];
 
@@ -1014,9 +1014,18 @@ public class DorisTableOperations extends 
JdbcTableOperations {
       TableChange.AddColumn addColumn, Optional<String> dorisVersion) {
     String dataType = typeConverter.fromGravitino(addColumn.getDataType());
     if (addColumn.fieldName().length > 1) {
-      throw new UnsupportedOperationException("Doris does not support nested 
column names.");
+      throw new IllegalArgumentException("Doris does not support nested column 
names.");
     }
     String col = addColumn.fieldName()[0];
+    // Doris 2.1.5+ and 3.0.1+ reject ADD COLUMN ... AUTO_INCREMENT. Earlier 
2.1.x and 3.0.0 accept
+    // it and record the flag, but never generate values for the added column.
+    if (addColumn.isAutoIncrement()) {
+      throw new IllegalArgumentException(
+          String.format(
+              "Doris does not support adding auto-increment column `%s`; "
+                  + "define auto-increment columns when creating the table",
+              col));
+    }
 
     StringBuilder columnDefinition = new StringBuilder();
     columnDefinition
@@ -1118,7 +1127,7 @@ public class DorisTableOperations extends 
JdbcTableOperations {
   private String updateColumnPositionFieldDefinition(
       TableChange.UpdateColumnPosition updateColumnPosition, JdbcTable 
jdbcTable) {
     if (updateColumnPosition.fieldName().length > 1) {
-      throw new UnsupportedOperationException("Doris does not support nested 
column names.");
+      throw new IllegalArgumentException("Doris does not support nested column 
names.");
     }
     String col = updateColumnPosition.fieldName()[0];
     JdbcColumn column = getJdbcColumnFromTable(jdbcTable, col);
@@ -1146,7 +1155,7 @@ public class DorisTableOperations extends 
JdbcTableOperations {
   private String deleteColumnFieldDefinition(
       TableChange.DeleteColumn deleteColumn, JdbcTable jdbcTable) {
     if (deleteColumn.fieldName().length > 1) {
-      throw new UnsupportedOperationException("Doris does not support nested 
column names.");
+      throw new IllegalArgumentException("Doris does not support nested column 
names.");
     }
     String col = deleteColumn.fieldName()[0];
     boolean colExists = true;
@@ -1170,7 +1179,7 @@ public class DorisTableOperations extends 
JdbcTableOperations {
       JdbcTable jdbcTable,
       Optional<String> dorisVersion) {
     if (updateColumnType.fieldName().length > 1) {
-      throw new UnsupportedOperationException("Doris does not support nested 
column names.");
+      throw new IllegalArgumentException("Doris does not support nested column 
names.");
     }
     String col = updateColumnType.fieldName()[0];
     JdbcColumn column = getJdbcColumnFromTable(jdbcTable, col);
diff --git 
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/operation/TestDorisTableOperationsSqlGeneration.java
 
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/operation/TestDorisTableOperationsSqlGeneration.java
index 86eea613d9..f13cd67a7c 100644
--- 
a/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/operation/TestDorisTableOperationsSqlGeneration.java
+++ 
b/catalogs/catalog-jdbc-doris/src/test/java/org/apache/gravitino/catalog/doris/operation/TestDorisTableOperationsSqlGeneration.java
@@ -34,6 +34,7 @@ import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Stream;
 import javax.sql.DataSource;
 import 
org.apache.gravitino.catalog.doris.converter.DorisColumnDefaultValueConverter;
 import org.apache.gravitino.catalog.doris.converter.DorisExceptionConverter;
@@ -56,6 +57,7 @@ import org.apache.gravitino.rel.types.Types;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.junit.jupiter.params.provider.ValueSource;
 import org.mockito.Mockito;
 
@@ -266,19 +268,19 @@ public class TestDorisTableOperationsSqlGeneration {
         ops.updateColumnTypeSql(unsetDefault, 
Types.LongType.get()).contains("bigint NULL ;"));
   }
 
-  /** Verifies nested column names remain unsupported for type changes. */
-  @Test
-  public void testUpdateColumnTypeRejectsNestedColumnName() {
+  /**
+   * Verifies rejected nested-column changes follow the alter-table exception 
contract.
+   *
+   * @param change the nested-column change to reject
+   */
+  @ParameterizedTest
+  @MethodSource("nestedColumnChanges")
+  public void testRejectsNestedColumnName(TableChange change) {
     TestableDorisTableOperations ops = new TestableDorisTableOperations();
 
-    UnsupportedOperationException exception =
+    IllegalArgumentException exception =
         Assertions.assertThrows(
-            UnsupportedOperationException.class,
-            () ->
-                ops.alterTableSql(
-                    "test_table",
-                    TableChange.updateColumnType(
-                        new String[] {"parent", "child"}, 
Types.LongType.get())));
+            IllegalArgumentException.class, () -> 
ops.alterTableSql("test_table", change));
 
     Assertions.assertEquals("Doris does not support nested column names.", 
exception.getMessage());
   }
@@ -474,6 +476,30 @@ public class TestDorisTableOperationsSqlGeneration {
     Assertions.assertTrue(alterSql.contains("COMMENT 'owner\\\\''s 
\"comment\"; --'"), alterSql);
   }
 
+  @Test
+  public void testAddAutoIncrementColumnIsRejected() {
+    TestableDorisTableOperations ops = new TestableDorisTableOperations();
+
+    IllegalArgumentException exception =
+        Assertions.assertThrows(
+            IllegalArgumentException.class,
+            () ->
+                ops.alterTableSql(
+                    "test_table",
+                    TableChange.addColumn(
+                        new String[] {"id"},
+                        Types.LongType.get(),
+                        null,
+                        TableChange.ColumnPosition.defaultPos(),
+                        false,
+                        true)));
+
+    Assertions.assertEquals(
+        "Doris does not support adding auto-increment column `id`; "
+            + "define auto-increment columns when creating the table",
+        exception.getMessage());
+  }
+
   @Test
   public void testAddColumnDefaultValuesInGeneratedSql() {
     TestableDorisTableOperations ops = new TestableDorisTableOperations();
@@ -1517,4 +1543,14 @@ public class TestDorisTableOperationsSqlGeneration {
     Mockito.when(resultSet.getString(1)).thenReturn(dorisVersion);
     return dataSource;
   }
+
+  private static Stream<TableChange> nestedColumnChanges() {
+    String[] fieldName = {"parent", "child"};
+    return Stream.of(
+        TableChange.addColumn(fieldName, Types.LongType.get()),
+        TableChange.updateColumnComment(fieldName, "new comment"),
+        TableChange.updateColumnPosition(fieldName, 
TableChange.ColumnPosition.first()),
+        TableChange.deleteColumn(fieldName, false),
+        TableChange.updateColumnType(fieldName, Types.LongType.get()));
+  }
 }
diff --git a/docs/jdbc-doris-catalog.md b/docs/jdbc-doris-catalog.md
index df94982bfa..0dea47a4f8 100644
--- a/docs/jdbc-doris-catalog.md
+++ b/docs/jdbc-doris-catalog.md
@@ -183,6 +183,8 @@ Doris enforces the following constraints (violations are 
rejected by the Doris s
 - The auto-increment column must be `BIGINT NOT NULL` with no `DEFAULT` value.
 - Each table can have at most one auto-increment column.
 
+An auto-increment column can only be defined when the table is created. 
Gravitino rejects adding one with `alterTable`.
+
 :::note
 Gravitino currently supports creating `UNIQUE KEY` tables via the `UNIQUE_KEY` 
index type. To create a `DUPLICATE KEY` table, omit key indexes from the table 
definition — Doris defaults to the DUPLICATE model when no key is specified.
 :::
diff --git 
a/plugins/tms/src/main/java/org/apache/gravitino/maintenance/storage/mapper/provider/h2/TableMaintenanceActionH2Provider.java
 
b/plugins/tms/src/main/java/org/apache/gravitino/maintenance/storage/mapper/provider/h2/TableMaintenanceActionH2Provider.java
index 835f656b70..ed2b84cd06 100644
--- 
a/plugins/tms/src/main/java/org/apache/gravitino/maintenance/storage/mapper/provider/h2/TableMaintenanceActionH2Provider.java
+++ 
b/plugins/tms/src/main/java/org/apache/gravitino/maintenance/storage/mapper/provider/h2/TableMaintenanceActionH2Provider.java
@@ -21,4 +21,13 @@ package 
org.apache.gravitino.maintenance.storage.mapper.provider.h2;
 import 
org.apache.gravitino.maintenance.storage.mapper.provider.base.TableMaintenanceActionBaseSQLProvider;
 
 /** H2 SQL provider for {@code table_maintenance_action}. */
-public class TableMaintenanceActionH2Provider extends 
TableMaintenanceActionBaseSQLProvider {}
+public class TableMaintenanceActionH2Provider extends 
TableMaintenanceActionBaseSQLProvider {
+
+  /** Returns H2 epoch milliseconds without rounding the fractional part 
across a second. */
+  @Override
+  protected String currentTimeMillisExpr() {
+    // H2 rounds CURRENT_TIMESTAMP(3) up near a second boundary, while 
UNIX_TIMESTAMP() truncates
+    // the original timestamp. Combining them can move the lease clock 
backwards by a second.
+    return "CAST(FLOOR(EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(9)) * 1000) AS 
BIGINT)";
+  }
+}
diff --git 
a/plugins/tms/src/test/java/org/apache/gravitino/maintenance/occupancy/TestOccupancyGate.java
 
b/plugins/tms/src/test/java/org/apache/gravitino/maintenance/occupancy/TestOccupancyGate.java
index f63532af35..0352388420 100644
--- 
a/plugins/tms/src/test/java/org/apache/gravitino/maintenance/occupancy/TestOccupancyGate.java
+++ 
b/plugins/tms/src/test/java/org/apache/gravitino/maintenance/occupancy/TestOccupancyGate.java
@@ -18,6 +18,8 @@
  */
 package org.apache.gravitino.maintenance.occupancy;
 
+import static 
org.apache.gravitino.maintenance.storage.TableMaintenanceActionTestUtils.expireClaim;
+
 import java.io.IOException;
 import java.util.function.Function;
 import org.apache.gravitino.Namespace;
@@ -200,7 +202,7 @@ class TestOccupancyGate extends TestJDBCBackend {
     TableEntity table = createAndInsertTableEntity(Namespace.of(metalakeName, 
"cat", "sch"), "tbl");
 
     TableMaintenanceActionMetaService actions = 
TableMaintenanceActionMetaService.getInstance();
-    long claimTimeoutMs = 200L;
+    long claimTimeoutMs = TableMaintenanceConfig.DEFAULT_CLAIM_TIMEOUT_MS;
     OccupancyGate gate = new OccupancyGate(actions, claimTimeoutMs);
     long policyId = 66L;
 
@@ -208,7 +210,7 @@ class TestOccupancyGate extends TestJDBCBackend {
     Assertions.assertTrue(actions.hasLiveUnboundClaim(table.id(), policyId, 
claimTimeoutMs));
     Assertions.assertTrue(gate.isInFlight(table.id(), policyId));
 
-    Thread.sleep(claimTimeoutMs + 50L);
+    expireClaim(claim, claimTimeoutMs);
 
     // Unbound TTL is evaluated in the DAO against the database clock, so 
OccupancyGate agrees with
     // acquire/reclaim even when the JVM clock would disagree (multi-node 
skew).
diff --git 
a/plugins/tms/src/test/java/org/apache/gravitino/maintenance/storage/TableMaintenanceActionTestUtils.java
 
b/plugins/tms/src/test/java/org/apache/gravitino/maintenance/storage/TableMaintenanceActionTestUtils.java
new file mode 100644
index 0000000000..a2913aece3
--- /dev/null
+++ 
b/plugins/tms/src/test/java/org/apache/gravitino/maintenance/storage/TableMaintenanceActionTestUtils.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.gravitino.maintenance.storage;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import org.apache.gravitino.maintenance.storage.service.OccupancyClaim;
+import org.apache.gravitino.storage.relational.session.SqlSessionFactoryHelper;
+import org.apache.ibatis.session.SqlSession;
+import org.junit.jupiter.api.Assertions;
+
+/** Database fixtures for maintenance-action lease tests. */
+public final class TableMaintenanceActionTestUtils {
+
+  private TableMaintenanceActionTestUtils() {}
+
+  /**
+   * Backdates an unbound claim without waiting for the database clock to 
advance.
+   *
+   * @param claim the claim to expire
+   * @param timeoutMs the lease timeout
+   * @return the expired claim carrying its updated fencing token
+   * @throws SQLException if the fixture cannot be updated
+   */
+  public static OccupancyClaim expireClaim(OccupancyClaim claim, long 
timeoutMs)
+      throws SQLException {
+    long expiredAt = claim.createdAt() - 2 * timeoutMs;
+    try (SqlSession session =
+            
SqlSessionFactoryHelper.getInstance().getSqlSessionFactory().openSession(true);
+        PreparedStatement statement =
+            session
+                .getConnection()
+                .prepareStatement(
+                    "UPDATE table_maintenance_action SET created_at = ? "
+                        + "WHERE id = ? AND job_id IS NULL AND finished_at = 
0")) {
+      statement.setLong(1, expiredAt);
+      statement.setLong(2, claim.id());
+      Assertions.assertEquals(1, statement.executeUpdate());
+    }
+    return new OccupancyClaim(claim.id(), expiredAt);
+  }
+}
diff --git 
a/plugins/tms/src/test/java/org/apache/gravitino/maintenance/storage/mapper/provider/h2/TestTableMaintenanceActionH2Provider.java
 
b/plugins/tms/src/test/java/org/apache/gravitino/maintenance/storage/mapper/provider/h2/TestTableMaintenanceActionH2Provider.java
new file mode 100644
index 0000000000..3364e51c4d
--- /dev/null
+++ 
b/plugins/tms/src/test/java/org/apache/gravitino/maintenance/storage/mapper/provider/h2/TestTableMaintenanceActionH2Provider.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.gravitino.maintenance.storage.mapper.provider.h2;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.time.Instant;
+import java.util.List;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+class TestTableMaintenanceActionH2Provider {
+
+  private static final class ExposedH2Provider extends 
TableMaintenanceActionH2Provider {
+    String clockExpression() {
+      return currentTimeMillisExpr();
+    }
+  }
+
+  @ParameterizedTest
+  @ValueSource(strings = {"UTC", "Asia/Shanghai", "America/Los_Angeles"})
+  void testClockDoesNotMoveBackwardsAtRoundingBoundary(String timeZone) throws 
Exception {
+    // Replace clock reads with one fixed input, retaining each requested 
timestamp precision.
+    // In particular, the old expression used unrounded seconds and rounded 
milliseconds.
+    String clockExpression =
+        new ExposedH2Provider()
+            .clockExpression()
+            .replace("UNIX_TIMESTAMP()", "UNIX_TIMESTAMP(clock_value)")
+            .replaceAll(
+                "CURRENT_TIMESTAMP\\((\\d+)\\)",
+                "CAST(clock_value AS TIMESTAMP($1) WITH TIME ZONE)");
+    String sql =
+        "SELECT "
+            + clockExpression
+            + " FROM (VALUES (CAST(? AS TIMESTAMP(9) WITH TIME ZONE))) AS 
clock(clock_value)";
+
+    try (Connection connection = 
DriverManager.getConnection("jdbc:h2:mem:tms_clock;MODE=MYSQL");
+        Statement statement = connection.createStatement();
+        PreparedStatement query = connection.prepareStatement(sql)) {
+      statement.execute("SET TIME ZONE '" + timeZone + "'");
+      for (String timestamp :
+          List.of(
+              "2026-10-19T00:00:00.999499Z",
+              "2026-10-19T00:00:00.999500Z",
+              "2026-10-19T00:00:01Z")) {
+        query.setString(1, timestamp);
+        try (ResultSet result = query.executeQuery()) {
+          Assertions.assertTrue(result.next());
+          Assertions.assertEquals(Instant.parse(timestamp).toEpochMilli(), 
result.getLong(1));
+        }
+      }
+    }
+  }
+}
diff --git 
a/plugins/tms/src/test/java/org/apache/gravitino/maintenance/storage/service/TestTableMaintenanceActionMetaService.java
 
b/plugins/tms/src/test/java/org/apache/gravitino/maintenance/storage/service/TestTableMaintenanceActionMetaService.java
index 5979eef5d8..e1b3d0c5a8 100644
--- 
a/plugins/tms/src/test/java/org/apache/gravitino/maintenance/storage/service/TestTableMaintenanceActionMetaService.java
+++ 
b/plugins/tms/src/test/java/org/apache/gravitino/maintenance/storage/service/TestTableMaintenanceActionMetaService.java
@@ -19,6 +19,8 @@
 
 package org.apache.gravitino.maintenance.storage.service;
 
+import static 
org.apache.gravitino.maintenance.storage.TableMaintenanceActionTestUtils.expireClaim;
+
 import java.util.Optional;
 import org.apache.gravitino.maintenance.TableMaintenanceConfig;
 import org.apache.gravitino.storage.relational.TestJDBCBackend;
@@ -79,23 +81,22 @@ class TestTableMaintenanceActionMetaService extends 
TestJDBCBackend {
     TableMaintenanceActionMetaService actions = 
TableMaintenanceActionMetaService.getInstance();
     long tableId = 11L;
     long policyId = 21L;
-    long timeoutMs = 200L;
+    long timeoutMs = TableMaintenanceConfig.DEFAULT_CLAIM_TIMEOUT_MS;
 
     Optional<OccupancyClaim> first = actions.tryAcquireInFlight(tableId, 
policyId, timeoutMs);
     Assertions.assertTrue(first.isPresent());
     Assertions.assertEquals(0L, 
actions.getById(first.get().id()).finishedAt());
     Assertions.assertTrue(actions.tryAcquireInFlight(tableId, policyId, 
timeoutMs).isEmpty());
 
-    Thread.sleep(timeoutMs + 50L);
+    OccupancyClaim expired = expireClaim(first.get(), timeoutMs);
 
     Optional<OccupancyClaim> reclaimed = actions.tryAcquireInFlight(tableId, 
policyId, timeoutMs);
     Assertions.assertTrue(reclaimed.isPresent());
     Assertions.assertEquals(first.get().id(), reclaimed.get().id());
-    Assertions.assertTrue(reclaimed.get().createdAt() >= 
first.get().createdAt());
+    Assertions.assertTrue(reclaimed.get().createdAt() > expired.createdAt());
     Assertions.assertEquals(0L, 
actions.getById(reclaimed.get().id()).finishedAt());
 
-    Assertions.assertThrows(
-        IllegalStateException.class, () -> actions.bindJobId(first.get(), 
1001L));
+    Assertions.assertThrows(IllegalStateException.class, () -> 
actions.bindJobId(expired, 1001L));
     actions.bindJobId(reclaimed.get(), 1002L);
     Assertions.assertEquals(1002L, 
actions.getById(reclaimed.get().id()).jobId());
   }

Reply via email to