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

sodonnell 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 0f7104eec0 HDDS-11708. Recon ListKeys API should return a proper http 
response status code if NSSummary rebuild is in progress. (#7437)
0f7104eec0 is described below

commit 0f7104eec040f41f690d52aba34b639f1b4ba370
Author: Devesh Kumar Singh <[email protected]>
AuthorDate: Tue Nov 19 19:47:33 2024 +0530

    HDDS-11708. Recon ListKeys API should return a proper http response status 
code if NSSummary rebuild is in progress. (#7437)
---
 .../org/apache/hadoop/ozone/recon/ReconUtils.java  |  7 +++---
 .../ozone/recon/api/OMDBInsightEndpoint.java       |  9 ++++---
 .../ozone/recon/api/ServiceNotReadyException.java  | 29 ++++++++++++++++++++++
 .../ozone/recon/api/TestContainerEndpoint.java     | 13 ++++++++++
 .../recon/api/TestNSSummaryEndpointWithFSO.java    | 13 ++++++----
 .../ozone/recon/api/TestOmDBInsightEndPoint.java   | 15 +++++++++++
 6 files changed, 74 insertions(+), 12 deletions(-)

diff --git 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/ReconUtils.java
 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/ReconUtils.java
index 830cf2e12d..407694bf85 100644
--- 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/ReconUtils.java
+++ 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/ReconUtils.java
@@ -80,6 +80,7 @@ import org.apache.hadoop.ozone.OmUtils;
 import org.apache.hadoop.ozone.OzoneConsts;
 import org.apache.hadoop.ozone.om.helpers.BucketLayout;
 import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
+import org.apache.hadoop.ozone.recon.api.ServiceNotReadyException;
 import org.apache.hadoop.ozone.recon.api.types.NSSummary;
 import org.apache.hadoop.ozone.recon.api.types.DUResponse;
 import org.apache.hadoop.ozone.recon.recovery.ReconOMMetadataManager;
@@ -356,16 +357,14 @@ public class ReconUtils {
       if (nsSummary == null) {
         log.warn("NSSummary tree is currently being rebuilt or the directory 
could be in the progress of " +
             "deletion, returning empty string for path construction.");
-        fullPath.setLength(0);
-        return fullPath;
+        throw new ServiceNotReadyException("Service is initializing. Please 
try again later.");
       }
       if (nsSummary.getParentId() == -1) {
         if (rebuildTriggered.compareAndSet(false, true)) {
           triggerRebuild(reconNamespaceSummaryManager, omMetadataManager);
         }
         log.warn("NSSummary tree is currently being rebuilt, returning empty 
string for path construction.");
-        fullPath.setLength(0);
-        return fullPath;
+        throw new ServiceNotReadyException("Service is initializing. Please 
try again later.");
       }
       // On the last pass, dir-name will be empty and parent will be zero, 
indicating the loop should end.
       if (!nsSummary.getDirName().isEmpty()) {
diff --git 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/OMDBInsightEndpoint.java
 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/OMDBInsightEndpoint.java
index abd3fae4fa..d7cb691253 100644
--- 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/OMDBInsightEndpoint.java
+++ 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/OMDBInsightEndpoint.java
@@ -976,7 +976,7 @@ public class OMDBInsightEndpoint {
     ListKeysResponse listKeysResponse = new ListKeysResponse();
     if (!ReconUtils.isInitializationComplete(omMetadataManager)) {
       listKeysResponse.setStatus(ResponseStatus.INITIALIZING);
-      return Response.ok(listKeysResponse).build();
+      return 
Response.status(Response.Status.SERVICE_UNAVAILABLE).entity(listKeysResponse).build();
     }
     ParamInfo paramInfo = new ParamInfo(replicationType, creationDate, 
keySize, startPrefix, prevKey,
         limit, false, "");
@@ -997,9 +997,9 @@ public class OMDBInsightEndpoint {
   }
 
   private Response getListKeysResponse(ParamInfo paramInfo) {
+    ListKeysResponse listKeysResponse = new ListKeysResponse();
     try {
       paramInfo.setLimit(Math.max(0, paramInfo.getLimit())); // Ensure limit 
is non-negative
-      ListKeysResponse listKeysResponse = new ListKeysResponse();
       listKeysResponse.setPath(paramInfo.getStartPrefix());
       long replicatedTotal = 0;
       long unreplicatedTotal = 0;
@@ -1009,7 +1009,6 @@ public class OMDBInsightEndpoint {
           omMetadataManager.getKeyTableLite(BucketLayout.LEGACY);
       retrieveKeysFromTable(keyTable, paramInfo, listKeysResponse.getKeys());
 
-
       // Search keys from FSO layout.
       searchKeysInFSO(paramInfo, listKeysResponse.getKeys());
 
@@ -1029,6 +1028,10 @@ public class OMDBInsightEndpoint {
 
       return Response.ok(listKeysResponse).build();
     } catch (RuntimeException e) {
+      if (e instanceof ServiceNotReadyException) {
+        listKeysResponse.setStatus(ResponseStatus.INITIALIZING);
+        return 
Response.status(Response.Status.SERVICE_UNAVAILABLE).entity(listKeysResponse).build();
+      }
       LOG.error("Error generating listKeys response", e);
       return ReconResponseUtils.createInternalServerErrorResponse(
           "Unexpected runtime error while searching keys in OM DB: " + 
e.getMessage());
diff --git 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/ServiceNotReadyException.java
 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/ServiceNotReadyException.java
new file mode 100644
index 0000000000..4190cc279c
--- /dev/null
+++ 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/ServiceNotReadyException.java
@@ -0,0 +1,29 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.hadoop.ozone.recon.api;
+
+/**
+ * This exception being thrown when Rest API service is still initializing and 
not yet ready.
+ */
+public class ServiceNotReadyException extends RuntimeException {
+  public ServiceNotReadyException(String message) {
+    super(message);
+  }
+}
+
diff --git 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestContainerEndpoint.java
 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestContainerEndpoint.java
index 3c39e4192d..da5484c9b8 100644
--- 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestContainerEndpoint.java
+++ 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestContainerEndpoint.java
@@ -62,10 +62,12 @@ import 
org.apache.hadoop.ozone.recon.scm.ReconContainerManager;
 import org.apache.hadoop.ozone.recon.scm.ReconPipelineManager;
 import org.apache.hadoop.ozone.recon.scm.ReconStorageContainerManagerFacade;
 import org.apache.hadoop.ozone.recon.spi.ReconContainerMetadataManager;
+import org.apache.hadoop.ozone.recon.spi.ReconNamespaceSummaryManager;
 import org.apache.hadoop.ozone.recon.spi.StorageContainerServiceProvider;
 import org.apache.hadoop.ozone.recon.spi.impl.OzoneManagerServiceProviderImpl;
 import 
org.apache.hadoop.ozone.recon.spi.impl.StorageContainerServiceProviderImpl;
 import org.apache.hadoop.ozone.recon.tasks.ContainerKeyMapperTask;
+import org.apache.hadoop.ozone.recon.tasks.NSSummaryTaskWithFSO;
 import 
org.hadoop.ozone.recon.schema.ContainerSchemaDefinition.UnHealthyContainerStates;
 import org.hadoop.ozone.recon.schema.tables.pojos.UnhealthyContainers;
 import org.junit.jupiter.api.BeforeEach;
@@ -121,6 +123,7 @@ public class TestContainerEndpoint {
       LoggerFactory.getLogger(TestContainerEndpoint.class);
 
   private OzoneStorageContainerManager ozoneStorageContainerManager;
+  private ReconNamespaceSummaryManager reconNamespaceSummaryManager;
   private ReconContainerManager reconContainerManager;
   private ContainerStateManager containerStateManager;
   private ReconPipelineManager reconPipelineManager;
@@ -198,6 +201,8 @@ public class TestContainerEndpoint {
     containerEndpoint = reconTestInjector.getInstance(ContainerEndpoint.class);
     containerHealthSchemaManager =
         reconTestInjector.getInstance(ContainerHealthSchemaManager.class);
+    this.reconNamespaceSummaryManager =
+        reconTestInjector.getInstance(ReconNamespaceSummaryManager.class);
 
     pipeline = getRandomPipeline();
     pipelineID = pipeline.getId();
@@ -472,6 +477,10 @@ public class TestContainerEndpoint {
     // Now to check if the ContainerEndpoint also reads the File table
     // Set up test data for FSO keys
     setUpFSOData();
+    NSSummaryTaskWithFSO nSSummaryTaskWithFso =
+        new NSSummaryTaskWithFSO(reconNamespaceSummaryManager,
+            reconOMMetadataManager, new OzoneConfiguration());
+    nSSummaryTaskWithFso.reprocessWithFSO(reconOMMetadataManager);
     // Reprocess the container key mapper to ensure the latest mapping is used
     reprocessContainerKeyMapper();
     response = containerEndpoint.getKeysForContainer(20L, -1, "");
@@ -556,6 +565,10 @@ public class TestContainerEndpoint {
     setUpFSOData();
     // Reprocess the container key mapper to ensure the latest mapping is used
     reprocessContainerKeyMapper();
+    NSSummaryTaskWithFSO nSSummaryTaskWithFso =
+        new NSSummaryTaskWithFSO(reconNamespaceSummaryManager,
+            reconOMMetadataManager, new OzoneConfiguration());
+    nSSummaryTaskWithFso.reprocessWithFSO(reconOMMetadataManager);
     response = containerEndpoint.getKeysForContainer(20L, -1, "/0/1/2/file7");
 
     // Ensure that the expected number of keys is returned
diff --git 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestNSSummaryEndpointWithFSO.java
 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestNSSummaryEndpointWithFSO.java
index 54da926601..9cda6d6e45 100644
--- 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestNSSummaryEndpointWithFSO.java
+++ 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestNSSummaryEndpointWithFSO.java
@@ -89,6 +89,7 @@ import static 
org.apache.hadoop.ozone.recon.OMMetadataManagerTestUtils.getMockOz
 import static 
org.apache.hadoop.ozone.recon.ReconServerConfigKeys.OZONE_RECON_NSSUMMARY_FLUSH_TO_DB_MAX_THRESHOLD;
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.anyLong;
@@ -791,8 +792,9 @@ public class TestNSSummaryEndpointWithFSO {
         .setParentObjectID(DIR_TWO_OBJECT_ID)
         .build();
     // Call constructFullPath and verify the result
-    fullPath = ReconUtils.constructFullPath(keyInfo,
-        reconNamespaceSummaryManager, reconOMMetadataManager);
+    OmKeyInfo finalKeyInfo = keyInfo;
+    assertThrows(ServiceNotReadyException.class, () -> 
ReconUtils.constructFullPath(finalKeyInfo,
+        reconNamespaceSummaryManager, reconOMMetadataManager));
   }
 
   @Test
@@ -813,8 +815,8 @@ public class TestNSSummaryEndpointWithFSO {
         .setParentObjectID(dirOneObjectId)
         .build();
 
-    String result = ReconUtils.constructFullPath(keyInfo, mockSummaryManager, 
mockMetadataManager);
-    assertEquals("", result, "Expected an empty string return due to rebuild 
trigger");
+    assertThrows(ServiceNotReadyException.class, () ->
+        ReconUtils.constructFullPath(keyInfo, mockSummaryManager, 
mockMetadataManager));
   }
 
   @Test
@@ -836,7 +838,8 @@ public class TestNSSummaryEndpointWithFSO {
         .setParentObjectID(1L)
         .build();
 
-    ReconUtils.constructFullPath(keyInfo, mockManager, null);
+    assertThrows(ServiceNotReadyException.class, () ->
+        ReconUtils.constructFullPath(keyInfo, mockManager, null));
 
     // Assert
     ArgumentCaptor<String> logCaptor = ArgumentCaptor.forClass(String.class);
diff --git 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOmDBInsightEndPoint.java
 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOmDBInsightEndPoint.java
index 398d494ea0..ed4b82fa3e 100644
--- 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOmDBInsightEndPoint.java
+++ 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOmDBInsightEndPoint.java
@@ -41,6 +41,7 @@ import 
org.apache.hadoop.ozone.recon.api.types.KeyEntityInfoProtoWrapper;
 import org.apache.hadoop.ozone.recon.api.types.KeyInsightInfoResponse;
 import org.apache.hadoop.ozone.recon.api.types.ListKeysResponse;
 import org.apache.hadoop.ozone.recon.api.types.NSSummary;
+import org.apache.hadoop.ozone.recon.api.types.ResponseStatus;
 import org.apache.hadoop.ozone.recon.persistence.AbstractReconSqlDBTest;
 import org.apache.hadoop.ozone.recon.persistence.ContainerHealthSchemaManager;
 import org.apache.hadoop.ozone.recon.recovery.ReconOMMetadataManager;
@@ -217,6 +218,7 @@ public class TestOmDBInsightEndPoint extends 
AbstractReconSqlDBTest {
   private static final long KEY_TWENTY_TWO_OBJECT_ID = 37L;
   private static final long KEY_TWENTY_THREE_OBJECT_ID = 38L;
   private static final long KEY_TWENTY_FOUR_OBJECT_ID = 39L;
+  private static final long KEY_TWENTY_FIVE_OBJECT_ID = 42L;
 
   private static final long EMPTY_OBS_BUCKET_OBJECT_ID = 40L;
   private static final long EMPTY_FSO_BUCKET_OBJECT_ID = 41L;
@@ -242,6 +244,7 @@ public class TestOmDBInsightEndPoint extends 
AbstractReconSqlDBTest {
   private static final long KEY_SEVENTEEN_SIZE = 2 * OzoneConsts.KB + 1; // 
bin 2
   private static final long KEY_EIGHTEEN_SIZE = OzoneConsts.KB + 1; // bin 1
   private static final long KEY_NINETEEN_SIZE = 2 * OzoneConsts.KB + 1; // bin 
2
+  private static final long KEY_TWENTY_SIZE = OzoneConsts.KB + 1; // bin 1
 
   private static final String OBS_BUCKET_PATH = "/volume1/obs-bucket";
   private static final String FSO_BUCKET_PATH = "/volume1/fso-bucket";
@@ -1940,6 +1943,18 @@ public class TestOmDBInsightEndPoint extends 
AbstractReconSqlDBTest {
     assertEquals("", listKeysResponse.getLastKey());
   }
 
+  @Test
+  public void testListKeysWhenNSSummaryNotInitialized() throws Exception {
+    reconNamespaceSummaryManager.clearNSSummaryTable();
+    // bucket level DU
+    Response bucketResponse =
+        omdbInsightEndpoint.listKeys("RATIS", "", 0, FSO_BUCKET_TWO_PATH,
+            "", 1000);
+    ListKeysResponse listKeysResponse = (ListKeysResponse) 
bucketResponse.getEntity();
+    assertEquals(ResponseStatus.INITIALIZING, listKeysResponse.getStatus());
+    assertEquals(Response.Status.SERVICE_UNAVAILABLE.getStatusCode(), 
bucketResponse.getStatus());
+  }
+
   @Test
   public void testListKeysForEmptyFSOBucket() {
     Response bucketResponse = omdbInsightEndpoint.listKeys("RATIS", "", 0, 
EMPTY_FSO_BUCKET_PATH,


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

Reply via email to