Copilot commented on code in PR #17494:
URL: https://github.com/apache/pinot/pull/17494#discussion_r2687887446


##########
pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotSegmentUploadDownloadRestletResource.java:
##########
@@ -984,29 +994,49 @@ public void uploadSegmentAsMultiPartV2(FormDataMultiPart 
multiPart,
   @Authenticate(AccessType.UPDATE)
   @Produces(MediaType.APPLICATION_JSON)
   @ApiOperation(value = "Start to replace segments", notes = "Start to replace 
segments")
-  public Response startReplaceSegments(
+  public void startReplaceSegments(
       @ApiParam(value = "Name of the table", required = true) 
@PathParam("tableName") String tableName,
       @ApiParam(value = "OFFLINE|REALTIME", required = true) 
@QueryParam("type") String tableTypeStr,
       @ApiParam(value = "Force cleanup") @QueryParam("forceCleanup") 
@DefaultValue("false") boolean forceCleanup,
       @ApiParam(value = "Fields belonging to start replace segment request", 
required = true)
-      StartReplaceSegmentsRequest startReplaceSegmentsRequest, @Context 
HttpHeaders headers) {
-    tableName = DatabaseUtils.translateTableName(tableName, headers);
-    TableType tableType = Constants.validateTableType(tableTypeStr);
-    if (tableType == null) {
-      throw new ControllerApplicationException(LOGGER, "Table type should 
either be offline or realtime",
-          Response.Status.BAD_REQUEST);
-    }
-    String tableNameWithType =
-        
ResourceUtils.getExistingTableNamesWithType(_pinotHelixResourceManager, 
tableName, tableType, LOGGER).get(0);
-    try {
-      String segmentLineageEntryId = 
_pinotHelixResourceManager.startReplaceSegments(tableNameWithType,
-          startReplaceSegmentsRequest.getSegmentsFrom(), 
startReplaceSegmentsRequest.getSegmentsTo(), forceCleanup,
-          startReplaceSegmentsRequest.getCustomMap());
-      return 
Response.ok(JsonUtils.newObjectNode().put("segmentLineageEntryId", 
segmentLineageEntryId)).build();
-    } catch (Exception e) {
-      _controllerMetrics.addMeteredTableValue(tableNameWithType, 
ControllerMeter.NUMBER_START_REPLACE_FAILURE, 1);
-      throw new ControllerApplicationException(LOGGER, e.getMessage(), 
Response.Status.INTERNAL_SERVER_ERROR, e);
-    }
+      StartReplaceSegmentsRequest startReplaceSegmentsRequest, @Context 
HttpHeaders headers,
+      @Suspended final AsyncResponse asyncResponse) {
+    _resourceExecutorService.execute(() -> {
+      try {
+        String translatedTableName = 
DatabaseUtils.translateTableName(tableName, headers);
+        TableType tableType = Constants.validateTableType(tableTypeStr);
+        if (tableType == null) {
+          asyncResponse.resume(
+              new ControllerApplicationException(LOGGER, "Table type should 
either be offline or realtime",
+                  Response.Status.BAD_REQUEST));
+          return;
+        }
+        String tableNameWithType =
+            
ResourceUtils.getExistingTableNamesWithType(_pinotHelixResourceManager, 
translatedTableName, tableType,
+                LOGGER).get(0);
+        String segmentLineageEntryId = 
_pinotHelixResourceManager.startReplaceSegments(tableNameWithType,
+            startReplaceSegmentsRequest.getSegmentsFrom(), 
startReplaceSegmentsRequest.getSegmentsTo(), forceCleanup,
+            startReplaceSegmentsRequest.getCustomMap());
+        asyncResponse.resume(
+            Response.ok(JsonUtils.newObjectNode().put("segmentLineageEntryId", 
segmentLineageEntryId)).build());
+      } catch (Exception e) {
+        String tableNameWithType = null;
+        try {
+          String translatedTableName = 
DatabaseUtils.translateTableName(tableName, headers);
+          TableType tableType = Constants.validateTableType(tableTypeStr);
+          if (tableType != null) {
+            tableNameWithType =
+                
ResourceUtils.getExistingTableNamesWithType(_pinotHelixResourceManager, 
translatedTableName, tableType,
+                    LOGGER).get(0);
+            _controllerMetrics.addMeteredTableValue(tableNameWithType, 
ControllerMeter.NUMBER_START_REPLACE_FAILURE, 1);
+          }
+        } catch (Exception ignored) {
+          // Ignore errors when trying to get table name for metrics
+        }

Review Comment:
   Duplicated error handling logic appears in three methods 
(startReplaceSegments, endReplaceSegments, revertReplaceSegments) at lines 
1023-1035, 1080-1092, and 1134-1147. This repetitive code should be extracted 
into a helper method that takes the operation name (for the appropriate 
ControllerMeter constant) as a parameter.



##########
pinot-controller/src/test/java/org/apache/pinot/controller/api/resources/PinotTaskRestletResourceTest.java:
##########
@@ -70,6 +81,12 @@ public void init()
       throws URISyntaxException {
     MockitoAnnotations.openMocks(this);
     when(_uriInfo.getRequestUri()).thenReturn(new 
URI("http://localhost:9000";));
+    // Make executor service execute tasks synchronously for testing
+    doAnswer(invocation -> {
+      Runnable runnable = invocation.getArgument(0);
+      runnable.run();
+      return null;
+    }).when(_minionTaskResourceExecutorService).execute(any(Runnable.class));

Review Comment:
   The test setup forces synchronous execution of async tasks, which doesn't 
verify the actual async behavior. While this simplifies testing, it fails to 
validate that the executor service is properly handling task submission, 
exception propagation, and concurrent execution scenarios that could occur in 
production.



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