nsivabalan commented on code in PR #18119:
URL: https://github.com/apache/hudi/pull/18119#discussion_r2776150610


##########
hudi-client/hudi-client-common/src/main/java/org/apache/hudi/client/transaction/SimpleConcurrentFileWritesConflictResolutionStrategy.java:
##########
@@ -164,8 +164,75 @@ public Option<HoodieCommitMetadata> 
resolveConflict(HoodieTable table,
       return thisOperation.getCommitMetadataOption();
     }
     // just abort the current write if conflicts are found
-    throw new HoodieWriteConflictException(new 
ConcurrentModificationException("Cannot resolve conflicts for overlapping 
writes between first operation = " + thisOperation
-        + ", second operation = " + otherOperation));
+    throw new HoodieWriteConflictException(new 
ConcurrentModificationException(buildConflictErrorMessage(thisOperation, 
otherOperation)));
+  }
+
+  /**
+   * Builds a detailed error message for write conflicts based on the 
operation types involved.
+   */
+  private String buildConflictErrorMessage(ConcurrentOperation thisOperation, 
ConcurrentOperation otherOperation) {
+    boolean otherIsTableService = 
isTableService(otherOperation.getOperationType());
+
+    String thisOpDesc = formatOperationDescription(thisOperation);
+    String otherOpDesc = formatOperationDescription(otherOperation);
+
+    // If other operation is a table service, provide specific retry guidance
+    if (otherIsTableService) {

Review Comment:
   we could do this when either of them is a table service and not both. 
   
   even clustering could hit this exception when it conflicts w/ ingestion 
writer. 
   
   
   



##########
hudi-client/hudi-client-common/src/main/java/org/apache/hudi/client/transaction/SimpleConcurrentFileWritesConflictResolutionStrategy.java:
##########
@@ -164,8 +164,75 @@ public Option<HoodieCommitMetadata> 
resolveConflict(HoodieTable table,
       return thisOperation.getCommitMetadataOption();
     }
     // just abort the current write if conflicts are found
-    throw new HoodieWriteConflictException(new 
ConcurrentModificationException("Cannot resolve conflicts for overlapping 
writes between first operation = " + thisOperation
-        + ", second operation = " + otherOperation));
+    throw new HoodieWriteConflictException(new 
ConcurrentModificationException(buildConflictErrorMessage(thisOperation, 
otherOperation)));
+  }
+
+  /**
+   * Builds a detailed error message for write conflicts based on the 
operation types involved.
+   */
+  private String buildConflictErrorMessage(ConcurrentOperation thisOperation, 
ConcurrentOperation otherOperation) {
+    boolean otherIsTableService = 
isTableService(otherOperation.getOperationType());
+
+    String thisOpDesc = formatOperationDescription(thisOperation);
+    String otherOpDesc = formatOperationDescription(otherOperation);
+
+    // If other operation is a table service, provide specific retry guidance
+    if (otherIsTableService) {
+      String serviceType = 
getTableServiceDisplayName(otherOperation.getOperationType());
+      return String.format(
+          "Cannot resolve conflicts for overlapping writes. %s is currently 
running and has overlapping file groups with %s. "
+              + "Please retry the write operation after the %s completes.",
+          otherOpDesc, thisOpDesc, serviceType.toLowerCase()
+      );
+    }
+
+    // For all other cases (this is table service or both are regular 
operations)
+    return String.format(
+        "Cannot resolve conflicts for overlapping writes. %s has overlapping 
file groups with %s.",
+        thisOpDesc, otherOpDesc
+    );
+  }
+
+  /**
+   * Formats a description of an operation including its type, instant, and 
state.
+   */
+  private String formatOperationDescription(ConcurrentOperation operation) {
+    String operationName = isTableService(operation.getOperationType())
+        ? "Table " + getTableServiceDisplayName(operation.getOperationType())
+        : operation.getOperationType().value() + " operation";
+
+    return String.format("%s (instant: %s, state: %s)",
+        operationName,
+        operation.getInstantTimestamp(),
+        operation.getInstantActionState());
+  }
+
+  /**
+   * Checks if the given operation type is a table service operation.
+   */
+  private boolean isTableService(WriteOperationType operationType) {

Review Comment:
   we could move this to `WriteOperationType` class only. 
   we already have few methods on similar nature placed there. 
   



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

Reply via email to