hudi-agent commented on code in PR #18439:
URL: https://github.com/apache/hudi/pull/18439#discussion_r3184598317


##########
hudi-client/hudi-client-common/src/main/java/org/apache/hudi/client/transaction/lock/StorageBasedLockProvider.java:
##########
@@ -346,9 +346,21 @@ public synchronized boolean tryLock() {
         newLockData,
         latestLock.getRight());
     if (lockUpdateStatus.getLeft() != LockUpsertResult.SUCCESS) {
-      // failed to acquire the lock, indicates concurrent contention
       logInfoLockState(FAILED_TO_ACQUIRE);
-      
hoodieLockMetrics.ifPresent(HoodieLockMetrics::updateLockAcquirePreconditionFailureMetric);
+      switch (lockUpdateStatus.getLeft()) {
+        case ACQUIRED_BY_OTHERS:
+          // failed to acquire the lock, indicates concurrent contention
+          
hoodieLockMetrics.ifPresent(HoodieLockMetrics::updateLockAcquirePreconditionFailureMetric);
+          break;
+        case THROTTLED:

Review Comment:
   🤖 nit: the comment "Lock state is unknown after the upsert attempt" doesn't 
quite fit the `THROTTLED` case — after a 429 the write was definitively 
rejected, so we know we didn't acquire the lock. "Unknown state" is accurate 
for `UNKNOWN_ERROR` but not for throttling. Could you split the comment, or 
rephrase to something like "Transient failure — the lock was not acquired; may 
succeed on retry"?
   
   <sub><i>- AI-generated; verify before applying. React 👍/👎 to flag 
quality.</i></sub>



##########
hudi-client/hudi-client-common/src/main/java/org/apache/hudi/client/transaction/lock/StorageBasedLockProvider.java:
##########
@@ -424,22 +436,55 @@ private boolean believesLockMightBeHeld() {
    * Unlock by marking our current lock file "expired": true.
    */
   @Override
-  public synchronized void unlock() {
-    assertHeartbeatManagerExists();
-    if (!believesLockMightBeHeld()) {
-      return;
+  public void unlock() {
+    ExpireLockResult expireResult;
+    // Snapshot the exact StorageLockFile we intend to expire. Identity 
comparison in the retry
+    // path guards against a concurrent tryLock() that, if our original lock 
had expired during
+    // the 1s sleep, could have installed a fresh lock that the retry must NOT 
mark expired.
+    StorageLockFile lockToExpire;
+    synchronized (this) {
+      assertHeartbeatManagerExists();
+      if (!believesLockMightBeHeld()) {
+        return;
+      }
+
+      // Try to stop the heartbeat first
+      if (heartbeatManager.hasActiveHeartbeat()) {
+        logger.debug("Owner {}: Gracefully shutting down heartbeat.", ownerId);
+        if (!heartbeatManager.stopHeartbeat(true)) {
+          
hoodieLockMetrics.ifPresent(HoodieLockMetrics::updateLockReleaseFailureMetric);
+          throw new 
HoodieLockException(generateLockStateMessage(FAILED_TO_RELEASE));
+        }
+      }
+
+      // Then expire the current lock.
+      lockToExpire = getLock();
+      expireResult = tryExpireCurrentLock(false);
     }
-    boolean believesNoLongerHoldsLock = true;
 
-    // Try to stop the heartbeat first
-    if (heartbeatManager.hasActiveHeartbeat()) {
-      logger.debug("Owner {}: Gracefully shutting down heartbeat.", ownerId);
-      believesNoLongerHoldsLock &= heartbeatManager.stopHeartbeat(true);
+    // If throttled, retry once after sleeping outside the monitor to avoid 
blocking other threads.
+    // Note: when unlock() is called via close() -> shutdown(), the caller's 
synchronized methods

Review Comment:
   🤖 nit: "the sleep will still block in that path" is a bit ambiguous — it 
reads as if the sleep is itself blocking, but the actual concern is that the 
outer `synchronized close()`/`shutdown()` caller still holds the monitor 
throughout the sleep. Could you rephrase to something like "the outer 
synchronized caller still holds the monitor through the sleep, so other threads 
remain blocked in that scenario"?
   
   <sub><i>- AI-generated; verify before applying. React 👍/👎 to flag 
quality.</i></sub>



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