mridulm commented on code in PR #37533:
URL: https://github.com/apache/spark/pull/37533#discussion_r968109053


##########
core/src/test/scala/org/apache/spark/scheduler/DAGSchedulerSuite.scala:
##########
@@ -4440,6 +4443,37 @@ class DAGSchedulerSuite extends SparkFunSuite with 
TempLocalSparkContext with Ti
     assert(mapStatuses.count(s => s != null && s.location.executorId == 
"hostB-exec") === 1)
   }
 
+  test("SPARK-40096: Send finalize events even if shuffle merger blocks 
indefinitely") {
+    initPushBasedShuffleConfs(conf)
+
+    val blockStoreClient = mock(classOf[ExternalBlockStoreClient])
+    val blockStoreClientField = 
classOf[BlockManager].getDeclaredField("blockStoreClient")
+    blockStoreClientField.setAccessible(true)
+    blockStoreClientField.set(sc.env.blockManager, blockStoreClient)
+    val sentHosts = ArrayBuffer[String]()
+    doAnswer { (invoke: InvocationOnMock) =>
+      val host = invoke.getArgument[String](0)
+      sentHosts += host
+      // Block FinalizeShuffleMerge rpc for 2 seconds
+      if (invoke.getArgument[String](0) == "hostA") {
+        Thread.sleep(2000)
+      }
+    }.when(blockStoreClient).finalizeShuffleMerge(any(), any(), any(), any(), 
any())
+
+    val shuffleMapRdd = new MyRDD(sc, 1, Nil)
+    val shuffleDep = new ShuffleDependency(shuffleMapRdd, new 
HashPartitioner(2))
+    shuffleDep.setMergerLocs(Seq(makeBlockManagerId("hostA"), 
makeBlockManagerId("hostB")))
+    val shuffleStage = scheduler.createShuffleMapStage(shuffleDep, 0)
+
+    Seq(true, false).foreach { registerMergeResults =>
+      sentHosts.clear()
+      scheduler.finalizeShuffleMerge(shuffleStage, registerMergeResults)
+      verify(blockStoreClient, times(2))
+        .finalizeShuffleMerge(any(), any(), any(), any(), any())
+      assert((sentHosts diff Seq("hostA", "hostB")).isEmpty)
+      reset(blockStoreClient)
+    }
+  }

Review Comment:
   This test should be essentially checking for merge finalize getting sent to 
`hostB` even though `hostA` is blocked
   
   Something like:
   
   ```
   initPushBasedShuffleConfs(conf)
   val timeoutSecs = 1
   conf.set("spark.shuffle.push.results.timeout", s"${timeoutSecs}s")
   
   ...
   
   val sendRequestsLatch = new CountDownLatch(shuffleDep.getMergerLocs.size)
   // does not necessary need to be latch, can be any other lock as well
   val canSendRequestLatch = new CountDownLatch(1)
   
   var hostAInterrupted = false
   doAnswer { (invoke: InvocationOnMock) =>
         sendRequestsLatch.countDown()
   
         val host = invoke.getArgument[String](0)
         // Block FinalizeShuffleMerge rpc until allowed by main thread
         try {
           if (invoke.getArgument[String](0) == "hostA") {
             // the actual value does not matter .... just high enough not to 
be affected by jitter
             canSendRequestLatch.await(timeoutSecs * 5, TimeUnit.SECONDS)
           }
           sentHosts += host
         } catch {
           case iEx: InterruptedException => hostAInterrupted = true
         }
       }.when(blockStoreClient).finalizeShuffleMerge(any(), any(), any(), 
any(), any())
   
   ...
       scheduler.finalizeShuffleMerge(shuffleStage, registerMergeResults)
       assert(sentHosts.toSeq === Seq("hostB"))
       assert(hostAInterrupted)
   
     ...
    
   ```
   
   Thoughts ?



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