j1wonpark commented on code in PR #4261:
URL: https://github.com/apache/amoro/pull/4261#discussion_r3524722828


##########
amoro-ams/src/main/java/org/apache/amoro/server/optimizing/TaskRuntime.java:
##########
@@ -82,9 +86,22 @@ public SimpleFuture getCompletedFuture() {
   }
 
   void complete(OptimizerThread thread, OptimizingTaskResult result) {
+    // A completion for an already reset/rescheduled task is stale: the 
execution it reports belongs
+    // to a round that the OptimizerKeeper has already torn down. Absorb it 
gracefully instead of
+    // failing the (now illegal) state transition; the task will be 
re-executed in its current
+    // round.
+    if (isStaleResponse(thread) || status != Status.ACKED) {

Review Comment:
   Thanks for the careful review — that's a sharp observation, and you're 
right. When the same task is re-scheduled to the same optimizer thread, 
`schedule()` re-assigns the identical token/threadId, so `(token, threadId, 
status)` has no way to tell a delayed completion of the previous round apart 
from the current one.
   
   For context on how I ended up leaving this window as-is in this PR: the 
behavior is the same before and after this change. The removed `validThread` 
relied on the same `(token, threadId)` key, and the state machine already 
accepted a thread-matching completion only at `ACKED` — so the pre-existing 
code accepted the same delayed completion in exactly the same window. This PR 
changes how the surrounding cases fail (graceful reject/ignore instead of a 
transaction error), but does not widen what gets accepted.
   
   Closing the window completely would need a per-attempt discriminator that 
the optimizer echoes back (e.g. an attempt id carried via the existing 
`OptimizingTask.properties` / `OptimizingTaskResult.summary` maps, compared in 
`complete()`), which requires changes on the optimizer client side as well. 
Since this PR doesn't change what gets accepted, I'd prefer to keep that 
improvement out of its scope and keep this PR focused on handling the stale 
responses gracefully on the AMS side.
   



##########
amoro-ams/src/test/java/org/apache/amoro/server/TestDefaultOptimizingService.java:
##########
@@ -314,6 +317,31 @@ public void testAckAndCompleteTask() {
     assertTaskCompleted(taskRuntime);
   }
 
+  // Reproduces the EXACT path of issue #4235 end-to-end with the real 
OptimizerKeeper: a live
+  // optimizer (the Toucher keeps heartbeating) polls a task but its ack is 
delayed past
+  // OPTIMIZER_TASK_ACK_TIMEOUT (30s). The keeper, via the SCHEDULED + 
ackTimeout branch of
+  // buildSuspendingPredication, resets the still-owned task to PLANNED. The 
late ack then arrives
+  // and is rejected -- this is the "Task has been reset or not yet scheduled" 
from the issue log,
+  // produced without any artificial retryTask() call.
+  @Test
+  public void testAckTimeoutResetThenLateAckRejected() throws 
InterruptedException {
+    OptimizingTask task = optimizingService().pollTask(token, THREAD_ID);
+    Assertions.assertNotNull(task);
+    assertTaskStatus(TaskRuntime.Status.SCHEDULED); // polled but NOT acked
+
+    // ack-timeout is 30s; the optimizer stays alive (Toucher touches every 
300ms), so this hits the
+    // SCHEDULED + ackTimeout branch rather than the optimizer-expired branch.
+    Thread.sleep(35000);

Review Comment:
   Good point, fixed in 515be61e65045a110fa2fe1319dc6f9fe6e97833. 
`OPTIMIZER_TASK_ACK_TIMEOUT` is now overridden in `AMSServiceTestBase` and the 
fixed 35s sleep is replaced with a 100ms status-polling wait, so the test 
finishes right after the keeper reset lands (~6s instead of 35s).
   
   One finding from trying the suggested 1-2s value: the ack timeout has to 
stay above `optimizer.polling-timeout` (3s). A `pollTask` blocking for its full 
polling timeout would otherwise pick up the very task the keeper reset by 
ack-timeout in the meantime — at 2s this broke `testPollTaskThreeTimes`, whose 
final poll expects `null`. So I settled on 5s and left a comment in 
`AMSServiceTestBase` documenting the constraint.
   



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