Yicong-Huang commented on code in PR #7122:
URL: https://github.com/apache/texera/pull/7122#discussion_r3782945782


##########
amber/src/test/scala/org/apache/texera/amber/engine/architecture/scheduling/RegionExecutionManagerSpec.scala:
##########
@@ -234,10 +254,11 @@ class RegionExecutionManagerSpec
     assert(fixture.rpcProbe.endWorkerCalls.size == fixture.workerIds.size * 2)
   }
 
-  it should "default to a bounded ~1.4s termination budget" in {
-    // 4 attempts from a 200 ms base, doubling: 200 + 400 + 800 ms = ~1.4 s of 
waiting, not the
-    // former 150 x 200 ms (~30 s). This is the documented contract for how 
long a stuck region
-    // blocks before failing loudly; pin it so changes are deliberate.
+  it should "default to a bounded ~25.4s termination budget" in {
+    // 4 attempts from a 200 ms base, doubling: 200 + 400 + 800 ms = ~1.4 s of 
backoff, plus
+    // a 6 s timeout per attempt. Worst-case teardown is now ~25.4 s. This is 
the documented
+    // contract for how long a stuck region blocks before failing loudly; pin 
it so changes
+    // are deliberate.
     assert(RegionExecutionManager.DefaultMaxTerminationAttempts == 4)
     assert(RegionExecutionManager.DefaultKillRetryBaseBackoffMs == 200L)

Review Comment:
   Verified: fixed. The rationale at `RegionExecutionManagerSpec.scala:258-261` 
now states one 6 s timeout per attempt and `~25.4 s` worst case, matching the 
class comment at `RegionExecutionManager.scala:74-77`, and `4 x 6000 + 
(200+400+800) = 25400 ms` checks out against the three constants the test pins 
at `:262-264`. The two-stage figure is gone from both places. Resolving.



##########
amber/src/test/scala/org/apache/texera/amber/engine/architecture/scheduling/RegionExecutionManagerSpec.scala:
##########
@@ -141,6 +141,45 @@ class RegionExecutionManagerSpec
     assert(workerState(fixture) == WorkerState.TERMINATED)
   }
 
+  it should "retry EndWorker when the termination timeout expires" in {
+    val fixture = createSingleRegionFixture(
+      endWorkerResponse = _ => None,
+      maxTerminationAttempts = 2,
+      killRetryBaseBackoffMs = fastRetryBackoffMs,
+      terminationTimeoutMs = 10L
+    )
+
+    launchRegion(fixture.manager)
+    val completion = requestRegionCompletion(fixture.manager)
+
+    val failure = intercept[IllegalStateException] {
+      await(completion)
+    }
+
+    assert(failure.getMessage.contains("could not be terminated after 2 
attempts"))
+    assert(fixture.rpcProbe.endWorkerCalls.size == 2)
+    assert(!fixture.manager.isCompleted)
+  }
+
+  it should "clean up control channels and actor refs after successful 
termination" in {

Review Comment:
   Verified: fixed by deletion, and nothing was lost with it. 
`assertControlChannelsAreRemoved` is still invoked at `:104`, inside `"send 
gracefulStop only after EndWorker succeeds"`, which also asserts `isCompleted` 
(`:101`) and `!hasActorRef` (`:102`) — every assertion the removed test made. 
Resolving.



##########
amber/src/test/scala/org/apache/texera/amber/engine/architecture/scheduling/RegionExecutionManagerSpec.scala:
##########
@@ -251,7 +293,8 @@ class RegionExecutionManagerSpec
     Time.withCurrentTimeFrozen { _ =>
       val fixture = createSingleRegionFixture(
         endWorkerResponse = _ => Some(transientEndWorkerFailure),
-        killRetryTimer = timer
+        killRetryTimer = timer,
+        terminationTimeoutMs = Long.MaxValue

Review Comment:
   Verified: fixed. Both call sites (`:277`, `:303`) now carry `// Disable the 
termination timeout for this frozen-time retry test.`, which names the intent a 
reader needs before `Long.MaxValue` reads as arbitrary. Resolving.



##########
amber/src/main/scala/org/apache/texera/amber/engine/architecture/scheduling/RegionExecutionManager.scala:
##########
@@ -195,41 +205,41 @@ class RegionExecutionManager(
           }
       }.toSeq
 
-    val endWorkerFuture: Future[Unit] =
-      Future.collect(endWorkerRequests).unit
-
-    // 2. Send GracefulStops only after 1 has finished
-    val gracefulStopRequests: Future[Unit] =
-      endWorkerFuture.flatMap { _ =>
-        val gracefulStops =
-          regionExecution.getAllOperatorExecutions.flatMap {
-            case (_, opExec) =>
-              opExec.getWorkerIds.map { workerId =>
-                val actorRef = actorRefService.getActorRef(workerId)
-                // Remove the actorRef so that no other actors can find the 
worker and send messages.
-                actorRefService.removeActorRef(workerId)
-                // Restarted regions reuse actorId. Remove stale control 
channels so the
-                // coordinator does not reuse old control-message sequence 
numbers for new workers.
-                asyncRPCClient.inputGateway.removeControlChannel(workerId)
-                asyncRPCClient.outputGateway.removeControlChannel(workerId)
-                gracefulStop(actorRef, ScalaDuration(5, 
TimeUnit.SECONDS)).asTwitter()
-              }
-          }.toSeq
+    val terminationAttempt =
+      Future
+        .collect(endWorkerRequests)
+        .unit
+        .flatMap { _ =>
+          // 2. Only send GracefulStops after all EndWorkers have succeeded.
+          val gracefulStopRequests =
+            regionExecution.getAllOperatorExecutions.flatMap {
+              case (_, opExec) =>
+                opExec.getWorkerIds.map { workerId =>
+                  val actorRef = actorRefService.getActorRef(workerId)
+                  gracefulStop(actorRef, ScalaDuration(5, 
TimeUnit.SECONDS)).asTwitter()
+                }
+            }.toSeq
 
-        Future.collect(gracefulStops).unit
-      }
+          Future.collect(gracefulStopRequests).unit
+        }
+        .within(killTimeout)
 
-    // 3. Log whether the kills were successful
-    gracefulStopRequests.transform {
+    // 3. Cleanup only after graceful termination succeeds.

Review Comment:
   Verified: applied at `:232`. Resolving.



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