Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e689419
[SPARK-XXXXX][CORE] Fail a pipelined group atomically on any member t…
jerrypeng Jul 11, 2026
23a1e44
[SPARK-XXXXX][CORE] Prevent cross-job/cross-time reuse of a pipelined…
jerrypeng Jul 11, 2026
04bd50e
[SPARK-XXXXX][CORE] Complete group-atomic failure (spec S6): fail a p…
jerrypeng Jul 11, 2026
6c0c3be
[SPARK-XXXXX][CORE] Test: group-atomic rerun resets per-partition com…
jerrypeng Jul 13, 2026
2632a33
[SPARK-XXXXX][CORE] Realign group-failure tests with the all-regular-…
jerrypeng Jul 19, 2026
7d0de62
[SPARK-XXXXX][CORE] Review round 1: make the SC-235532 executor-loss …
jerrypeng Jul 19, 2026
ac37156
[SPARK-XXXXX][CORE] Replace internal ticket/milestone references with…
jerrypeng Jul 20, 2026
e024cef
[SPARK-XXXXX][CORE] Gate the per-submit pipelined-group check on a ch…
jerrypeng Jul 20, 2026
37e3597
[SPARK-XXXXX][CORE] Clarify that a pipelined shuffle's MapOutputTrack…
jerrypeng Jul 20, 2026
e433a1e
[SPARK-XXXXX][CORE] Test the finishOnly-replay-on-torn-down-stage gua…
jerrypeng Jul 20, 2026
51f1ccf
[SPARK-XXXXX][CORE] Test: explicit job cancellation cleans up a buffe…
jerrypeng Jul 20, 2026
bf81dd1
[SPARK-XXXXX][CORE] Test: a consumer result task throwing aborts the …
jerrypeng Jul 20, 2026
0285b70
[SPARK-XXXXX][CORE] Remove internal jargon from pipelined-shuffle com…
jerrypeng Jul 21, 2026
af0d541
[SPARK-XXXXX][CORE] Remove the obsolete finishOnly-replay-on-torn-dow…
jerrypeng Jul 23, 2026
0d43567
[SPARK-XXXXX][CORE] Fail fast on unsupported idioms in a pipelined group
jerrypeng Jul 13, 2026
d491c77
[SPARK-XXXXX][CORE] Reject reliable checkpoint in a pipelined CONSUME…
jerrypeng Jul 13, 2026
c331c12
[SPARK-XXXXX][CORE] Test: multi-producer consumer drops buffered succ…
jerrypeng Jul 19, 2026
86110e8
[SPARK-XXXXX][CORE] Review round 1: fix checkPipelinedProducerSupport…
jerrypeng Jul 19, 2026
a109071
[SPARK-XXXXX][CORE] Test: a deferred consumer's TaskEnd fires inline,…
jerrypeng Jul 20, 2026
48db5e8
[SPARK-XXXXX][CORE] Pipelined fail-fast: match a typed exception, and…
jerrypeng Jul 20, 2026
d5f8686
[SPARK-XXXXX][CORE] Reject any non-default resource profile in a pipe…
jerrypeng Jul 20, 2026
11f46a7
[SPARK-XXXXX][CORE] Enforce the v1 job==group admission invariant; de…
jerrypeng Jul 20, 2026
692da31
[SPARK-XXXXX][CORE] Make the job==group admission invariant fail-clos…
jerrypeng Jul 21, 2026
6945e2d
[SPARK-XXXXX][CORE] Remove internal jargon from pipelined-shuffle com…
jerrypeng Jul 21, 2026
a2c0267
[SPARK-XXXXX][CORE] Supersede the pr3 resource-profile guard with the…
jerrypeng Jul 23, 2026
9f82734
[SPARK-XXXXX][CORE] Realign the group-abort deferral test with the co…
jerrypeng Jul 23, 2026
8fe4a72
[SPARK-XXXXX][CORE] Gate the pipelined group-idiom check on hasPipeli…
jerrypeng Jul 23, 2026
1d88366
[SPARK-XXXXX][CORE] Fix scalastyle line-length in the RP-inertness te…
jerrypeng Jul 24, 2026
ebcaa06
[SPARK-XXXXX][CORE] Rework the fan-out admission-demand tests to asse…
jerrypeng Jul 28, 2026
364a18e
[SPARK-XXXXX][CORE] Register a pipelined shuffle with the streaming o…
jerrypeng Jul 22, 2026
d6341d2
[SPARK-XXXXX][SQL] Let ShuffleExchangeExec build a pipelined shuffle …
jerrypeng Jul 22, 2026
351e035
[SPARK-XXXXX][SS] Run stateful Real-Time Mode queries over a pipeline…
jerrypeng Jul 22, 2026
4264a6c
[SPARK-XXXXX][SS][TESTS] Test stateful dedup running in Real-Time Mod…
jerrypeng Jul 22, 2026
2d50387
[SPARK-XXXXX][SS][TESTS] Test dedup fault-tolerance in Real-Time Mode…
jerrypeng Jul 22, 2026
e01c3af
[SPARK-XXXXX][SS][TESTS] Test dedup checkpoint-write-failure recovery…
jerrypeng Jul 22, 2026
ab4234f
[SPARK-XXXXX][CORE] Unregister a pipelined shuffle from the streaming…
jerrypeng Jul 27, 2026
e27c581
[SPARK-XXXXX][CORE] Fully separate pipelined shuffles from the MapOut…
jerrypeng Jul 28, 2026
b64c393
[SPARK-XXXXX][CORE] Harden the MapOutputTracker decoupling: fail loud…
jerrypeng Jul 28, 2026
ae85d3f
[SPARK-XXXXX][SS] Fix scalastyle line length and document the RTM sin…
jerrypeng Jul 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions common/utils/src/main/resources/error/error-conditions.json
Original file line number Diff line number Diff line change
Expand Up @@ -6399,6 +6399,18 @@
],
"sqlState" : "42K03"
},
"PIPELINED_SHUFFLE_CROSS_JOB_REUSE" : {
"message" : [
"The pipelined shuffle <shuffleId> is being reused across jobs. A pipelined (incrementally-readable) shuffle is transient and has no retained output for another job to read, so its producer stage cannot be shared across jobs."
],
"sqlState" : "0A000"
},
"PIPELINED_SHUFFLE_UNSUPPORTED" : {
"message" : [
"A pipelined shuffle stage group cannot be scheduled because it uses an unsupported feature: <reason>. Pipelined (incrementally-readable) shuffles run their producer and consumer stages concurrently over a transient, once-through stream, which is incompatible with this feature in this version."
],
"sqlState" : "0A000"
},
"PIPELINE_DATASET_WITHOUT_FLOW" : {
"message" : [
"Pipeline dataset <identifier> does not have any defined flows. Please attach a query with the dataset's definition, or explicitly define at least one flow that writes to the dataset."
Expand Down
14 changes: 14 additions & 0 deletions core/src/main/scala/org/apache/spark/ContextCleaner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ private[spark] class ContextCleaner(
/** Perform shuffle cleanup. */
def doCleanupShuffle(shuffleId: Int, blocking: Boolean): Unit = {
try {
// A shuffle lives in exactly one tracker, split by dependency type: a regular shuffle in the
// MapOutputTracker, a pipelined shuffle in the driver-only StreamingShuffleOutputTracker (see
// DAGScheduler.createShuffleMapStage). Clean up whichever holds it -- the two branches are
// independent, each keyed on its own tracker's membership, so neither depends on the other.
if (mapOutputTrackerMaster.containsShuffle(shuffleId)) {
logDebug("Cleaning shuffle " + shuffleId)
// Shuffle must be removed before it's unregistered from the output tracker
Expand All @@ -244,6 +248,14 @@ private[spark] class ContextCleaner(
mapOutputTrackerMaster.unregisterShuffle(shuffleId)
listeners.asScala.foreach(_.shuffleCleaned(shuffleId))
logDebug("Cleaned shuffle " + shuffleId)
} else if (streamingShuffleOutputTrackerMaster.exists(_.containsShuffle(shuffleId))) {
// A pipelined shuffle's state is driver-only (the worker tracker caches nothing), so
// cleanup is a direct driver-side unregister. No RemoveShuffle RPC is needed: a streaming
// shuffle has no durable, block-manager-served files to remove.
logDebug("Cleaning pipelined shuffle " + shuffleId)
streamingShuffleOutputTrackerMaster.foreach(_.unregisterShuffle(shuffleId))
listeners.asScala.foreach(_.shuffleCleaned(shuffleId))
logDebug("Cleaned pipelined shuffle " + shuffleId)
} else {
logDebug("Asked to cleanup non-existent shuffle (maybe it was already removed)")
}
Expand Down Expand Up @@ -308,6 +320,8 @@ private[spark] class ContextCleaner(

private def broadcastManager = sc.env.broadcastManager
private def mapOutputTrackerMaster = sc.env.mapOutputTracker.asInstanceOf[MapOutputTrackerMaster]
private def streamingShuffleOutputTrackerMaster: Option[StreamingShuffleOutputTrackerMaster] =
sc.env.streamingShuffleOutputTracker.map(_.asInstanceOf[StreamingShuffleOutputTrackerMaster])
}

private object ContextCleaner {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ private[spark] class StreamingShuffleOutputTrackerMaster(conf: SparkConf)
}
}

// Whether the given shuffle is registered. ContextCleaner uses this on the driver to skip
// regular (non-pipelined) shuffles, which are never registered here, before unregistering.
def containsShuffle(shuffleId: Int): Boolean = shuffleInfos.containsKey(shuffleId)

// for testing purposes
private[spark] def getShuffleInfo(shuffleId: Int): Option[StreamingShuffleInfo] = {
Option(shuffleInfos.get(shuffleId))
Expand Down
22 changes: 22 additions & 0 deletions core/src/main/scala/org/apache/spark/scheduler/ActiveJob.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,26 @@ private[spark] class ActiveJob(
val finished = Array.fill[Boolean](numPartitions)(false)

var numFinished = 0

/**
* Whether this job's RDD graph uses a `PipelinedShuffleDependency` (set once at job submission).
* Every pipelined-group scheduling path -- co-scheduling, deferral, and the per-submit
* `TaskSet.isPipelined` tagging -- is inert for a job without one, so this flag lets those paths
* short-circuit the group-membership graph walk for the common regular job at no cost.
*/
var hasPipelinedDependency: Boolean = false

/**
* True once this job's pipelined group has passed up-front gang admission in
* `handleJobSubmitted` (or the slot check was disabled by config). This is a distinct fact from
* `hasPipelinedDependency` (which only says the job uses pipelining): the co-schedule path in
* `DAGScheduler.submitStage` gang-schedules a group's members with NO slot check, and checks this
* flag so that trust in up-front admission is enforced rather than merely commented.
*
* The whole job is a single pipelined group, so admission is a job-level fact. If a future change
* allows multiple groups per job, this job-level flag must be replaced by per-group admission
* state, and the check in `submitStage` replaced by that per-group gate -- NOT simply deleted, or
* an unadmitted group could be gang-scheduled and deadlock.
*/
var pipelinedGroupAdmitted: Boolean = false
}
Loading