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

sumitagrawal 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 17dbc4f134 HDDS-12585. Recon ContainerHealthTask 
ConstraintViolationException error handling. (#8070)
17dbc4f134 is described below

commit 17dbc4f134caf8978f887ac482feef4ab7f12e4c
Author: Devesh Kumar Singh <[email protected]>
AuthorDate: Thu Mar 20 10:12:24 2025 +0530

    HDDS-12585. Recon ContainerHealthTask ConstraintViolationException error 
handling. (#8070)
---
 .../persistence/ContainerHealthSchemaManager.java  | 35 +++++++++--
 .../ozone/recon/fsck/TestContainerHealthTask.java  | 67 +++++++++++++++++++++-
 2 files changed, 95 insertions(+), 7 deletions(-)

diff --git 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/persistence/ContainerHealthSchemaManager.java
 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/persistence/ContainerHealthSchemaManager.java
index 3ee679bb80..84222fc6cc 100644
--- 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/persistence/ContainerHealthSchemaManager.java
+++ 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/persistence/ContainerHealthSchemaManager.java
@@ -17,6 +17,7 @@
 
 package org.apache.hadoop.ozone.recon.persistence;
 
+import static 
org.apache.ozone.recon.schema.ContainerSchemaDefinition.UNHEALTHY_CONTAINERS_TABLE_NAME;
 import static 
org.apache.ozone.recon.schema.ContainerSchemaDefinition.UnHealthyContainerStates.ALL_REPLICAS_BAD;
 import static 
org.apache.ozone.recon.schema.ContainerSchemaDefinition.UnHealthyContainerStates.UNDER_REPLICATED;
 import static 
org.apache.ozone.recon.schema.generated.tables.UnhealthyContainersTable.UNHEALTHY_CONTAINERS;
@@ -24,6 +25,7 @@
 
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
+import java.sql.Connection;
 import java.util.List;
 import org.apache.hadoop.ozone.recon.api.types.UnhealthyContainersSummary;
 import org.apache.ozone.recon.schema.ContainerSchemaDefinition;
@@ -35,6 +37,7 @@
 import org.jooq.DSLContext;
 import org.jooq.Record;
 import org.jooq.SelectQuery;
+import org.jooq.exception.DataAccessException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -118,12 +121,34 @@ public Cursor<UnhealthyContainersRecord> 
getAllUnhealthyRecordsCursor() {
 
   public void insertUnhealthyContainerRecords(List<UnhealthyContainers> recs) {
     if (LOG.isDebugEnabled()) {
-      recs.forEach(rec -> {
-        LOG.debug("rec.getContainerId() : {}, rec.getContainerState(): {} ", 
rec.getContainerId(),
-            rec.getContainerState());
-      });
+      recs.forEach(rec -> LOG.debug("rec.getContainerId() : {}, 
rec.getContainerState(): {}",
+          rec.getContainerId(), rec.getContainerState()));
+    }
+
+    try (Connection connection = 
containerSchemaDefinition.getDataSource().getConnection()) {
+      connection.setAutoCommit(false); // Turn off auto-commit for 
transactional control
+      try {
+        for (UnhealthyContainers rec : recs) {
+          try {
+            unhealthyContainersDao.insert(rec);
+          } catch (DataAccessException dataAccessException) {
+            // Log the error and update the existing record if 
ConstraintViolationException occurs
+            unhealthyContainersDao.update(rec);
+            LOG.debug("Error while inserting unhealthy container record: {}", 
rec, dataAccessException);
+          }
+        }
+        connection.commit(); // Commit all inserted/updated records
+      } catch (Exception innerException) {
+        connection.rollback(); // Rollback transaction if an error occurs 
inside processing
+        LOG.error("Transaction rolled back due to error", innerException);
+        throw innerException;
+      } finally {
+        connection.setAutoCommit(true); // Reset auto-commit before the 
connection is auto-closed
+      }
+    } catch (Exception e) {
+      LOG.error("Failed to insert records into {} ", 
UNHEALTHY_CONTAINERS_TABLE_NAME, e);
+      throw new RuntimeException("Recon failed to insert " + recs.size() + " 
unhealthy container records.", e);
     }
-    unhealthyContainersDao.insert(recs);
   }
 
 }
diff --git 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/fsck/TestContainerHealthTask.java
 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/fsck/TestContainerHealthTask.java
index a5e891f1cd..bdd5ca35b2 100644
--- 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/fsck/TestContainerHealthTask.java
+++ 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/fsck/TestContainerHealthTask.java
@@ -25,9 +25,9 @@
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -494,6 +494,69 @@ public void testAllContainerStateInsertions() {
     }
   }
 
+  @Test
+  public void testInsertFailureAndUpdateBehavior() {
+    UnhealthyContainersDao unHealthyContainersTableHandle =
+        getDao(UnhealthyContainersDao.class);
+
+    ContainerHealthSchemaManager containerHealthSchemaManager =
+        new ContainerHealthSchemaManager(
+            getSchemaDefinition(ContainerSchemaDefinition.class),
+            unHealthyContainersTableHandle);
+
+    ContainerSchemaDefinition.UnHealthyContainerStates state =
+        ContainerSchemaDefinition.UnHealthyContainerStates.MISSING;
+
+    long insertedTime = System.currentTimeMillis();
+    // Create a dummy UnhealthyContainer record with the current state
+    UnhealthyContainers unhealthyContainer = new UnhealthyContainers();
+    unhealthyContainer.setContainerId(state.ordinal() + 1L);
+    unhealthyContainer.setExpectedReplicaCount(3);
+    unhealthyContainer.setActualReplicaCount(0);
+    unhealthyContainer.setReplicaDelta(3);
+    unhealthyContainer.setContainerState(state.name());
+    unhealthyContainer.setInStateSince(insertedTime);
+
+    // Try inserting the record and catch any exception that occurs
+    Exception exception = null;
+    try {
+      containerHealthSchemaManager.insertUnhealthyContainerRecords(
+          Collections.singletonList(unhealthyContainer));
+    } catch (Exception e) {
+      exception = e;
+    }
+
+    // Assert no exception should be thrown for each state
+    assertNull(exception,
+        "Exception was thrown during insertion for state " + state.name() +
+            ": " + exception);
+
+    long updatedTime = System.currentTimeMillis();
+    unhealthyContainer.setExpectedReplicaCount(3);
+    unhealthyContainer.setActualReplicaCount(0);
+    unhealthyContainer.setReplicaDelta(3);
+    unhealthyContainer.setContainerState(state.name());
+    unhealthyContainer.setInStateSince(updatedTime);
+
+    try {
+      containerHealthSchemaManager.insertUnhealthyContainerRecords(
+          Collections.singletonList(unhealthyContainer));
+    } catch (Exception e) {
+      exception = e;
+    }
+
+    // Optionally, verify the record was updated correctly
+    List<UnhealthyContainers> updatedRecords =
+        unHealthyContainersTableHandle.fetchByContainerId(
+            state.ordinal() + 1L);
+    assertFalse(updatedRecords.isEmpty(),
+        "Record was not updated for state " + state.name() + ".");
+    assertEquals(updatedRecords.get(0).getContainerState(), state.name(),
+        "The inserted container state does not match for state " +
+            state.name() + ".");
+    assertEquals(updatedRecords.get(0).getInStateSince(), updatedTime);
+  }
+
   @Test
   public void testMissingAndEmptyMissingContainerDeletion() throws Exception {
     // Setup mock DAOs and managers


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

Reply via email to