jerrypeng commented on code in PR #59523:
URL: https://github.com/apache/spark/pull/59523#discussion_r4429459388


##########
core/src/test/scala/org/apache/spark/shuffle/local/pipelined/PipelinedChannelShuffleSuite.scala:
##########
@@ -685,6 +686,64 @@ class PipelinedChannelShuffleSuite extends SparkFunSuite {
     }
   }
 
+  for (cachedPartitions <- Seq(0, 1, 2)) {
+    test(s"consumer cache is rejected before channel tasks start 
(cached=$cachedPartitions)") {
+      withPipelinedSparkContext(cores = 4) { sc =>
+        val input = sc.parallelize(0 until 1000, 2).map(i => (i, i))
+        val consumer = new PipelinedShuffledRDD[Int, Int, Int](input, new 
HashPartitioner(2))
+          .cache()
+        val blocks = consumer.partitions.indices.map(RDDBlockId(consumer.id, 
_))
+        val blockManager = sc.env.blockManager
+        // Populate blocks without running the shuffle so a partial cache 
cannot leave a
+        // producer waiting for a reader during setup.
+        blocks.take(cachedPartitions).foreach { block =>
+          assert(blockManager.putIterator(
+            block, Iterator((block.splitIndex, block.splitIndex)),
+            StorageLevel.MEMORY_ONLY, tellMaster = true))
+        }
+        
assert(blockManager.master.getLocations(blocks.toArray[BlockId]).map(_.nonEmpty).toSeq
 ===
+          blocks.indices.map(_ < cachedPartitions))
+
+        val events = new JobEvents
+        sc.addSparkListener(events)
+        val error = intercept[SparkException](consumer.collect())
+        checkError(
+          exception = error,
+          condition = "PIPELINED_SHUFFLE_UNSUPPORTED",
+          sqlState = Some("0A000"),
+          parameters = Map("reason" ->
+            (s"cache/persist/localCheckpoint on RDD $consumer in a pipelined 
consumer's " +
+              "within-stage chain (unpersist this RDD or rebuild it without 
localCheckpoint " +
+              "before submitting the job; persist only RDDs that do not read a 
pipelined " +
+              "shuffle within their stage)")))
+        sc.listenerBus.waitUntilEmpty()
+        assert(events.taskStarts.isEmpty)
+        assert(events.stageEnds.isEmpty)
+        assert(ChannelShuffleRendezvous.numQueuesForTesting === 0)
+        assert(consumer.getStorageLevel === StorageLevel.MEMORY_ONLY)
+
+        consumer.unpersist(blocking = true)
+        for (_ <- 0 until 2) {
+          assert(consumer.collect().map(_._1).sorted === (0 until 
1000).toArray)
+          assert(ChannelShuffleRendezvous.numQueuesForTesting === 0)
+        }
+      }
+    }
+  }
+
+  test("cached producer input survives eviction between pipelined actions") {

Review Comment:
   Renamed the test to “pipelined actions recompute an evicted producer-input 
cache”. The cached blocks are removed while persistence intent remains set, and 
the second pipelined action succeeds by recomputing the producer input.



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