Commit 710b3c4
committed
[SPARK-56972][SS][FOLLOWUP] Reject sink evolution combined with async progress tracking
### What changes were proposed in this pull request?
Follow-up to #56020 (SPARK-56972), which added V3 commit-log persistence of sink metadata inside `MicroBatchExecution.markMicroBatchEnd`. Two issues:
1. **Async progress tracking silently drops sink metadata.** `AsyncProgressTrackingMicroBatchExecution` overrides `markMicroBatchEnd` and writes only V1 commit metadata through its async path; it never goes through the V3 write the parent added. So when both `spark.sql.streaming.queryEvolution.enableSinkEvolution` and `asyncProgressTrackingEnabled` are on, the sink metadata is silently never persisted. This PR rejects the combination explicitly at query start (mirroring the existing async validations for `Once`/`AvailableNow` triggers and unsupported sinks), so the durability gap fails loudly instead of silently.
2. **`sinkMetadataMap` doc comment was inaccurate.** It claimed insertion order is preserved "so that we can re-emit deactivated sinks in the same order they originally appeared", but the order is not upheld end-to-end: the commit-log write rebuilds the map via `.toMap` and the field round-trips through an unordered serialized `Map` on restart. The active sink is found by its `isActive` flag, not by position, so order is never consumed. The comment also referenced `runBatch` as the mutation site when the mutation actually lives in `markMicroBatchEnd`. Fixed the comment and switched the field to a plain `mutable.HashMap`.
### Why are the changes needed?
The first change is a correctness fix: a user enabling sink evolution together with async progress tracking would get no error and no persisted sink metadata, defeating the feature's durability guarantee with no signal. The second keeps the in-code documentation honest so a future maintainer does not rely on an ordering guarantee that does not hold.
### Does this PR introduce _any_ user-facing change?
Yes, but only for the unreleased sink-evolution feature (off by default). A streaming query that sets both `spark.sql.streaming.queryEvolution.enableSinkEvolution=true` and `asyncProgressTrackingEnabled=true` now fails at start with `IllegalArgumentException("Async progress tracking cannot be used with streaming sink evolution (spark.sql.streaming.queryEvolution.enableSinkEvolution)")` instead of running while silently not persisting the sink metadata.
### How was this patch tested?
Added `AsyncProgressTrackingMicroBatchExecutionSuite."Fail with streaming sink evolution enabled"`, which asserts the new validation error. Existing `AsyncProgressTrackingMicroBatchExecutionSuite` and `StreamingSinkEvolutionSuite` (12 tests) pass with the `HashMap` change.
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (claude-opus-4-8)
This pull request and its description were written by Isaac.
Closes #56692 from cloud-fan/SPARK-56972-followup.
Authored-by: Wenchen Fan <wenchen@databricks.com>
Signed-off-by: Wenchen Fan <wenchen@databricks.com>1 parent b6f2fa0 commit 710b3c4
4 files changed
Lines changed: 67 additions & 5 deletions
File tree
- common/utils/src/main/resources/error
- sql/core/src
- main/scala/org/apache/spark/sql
- classic
- execution/streaming/runtime
- test/scala/org/apache/spark/sql/execution/streaming
Lines changed: 5 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7322 | 7322 | | |
7323 | 7323 | | |
7324 | 7324 | | |
| 7325 | + | |
| 7326 | + | |
| 7327 | + | |
| 7328 | + | |
| 7329 | + | |
7325 | 7330 | | |
7326 | 7331 | | |
7327 | 7332 | | |
| |||
Lines changed: 11 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
239 | 239 | | |
240 | 240 | | |
241 | 241 | | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
242 | 253 | | |
243 | 254 | | |
244 | 255 | | |
| |||
sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/runtime/MicroBatchExecution.scala
Lines changed: 5 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
129 | 129 | | |
130 | 130 | | |
131 | 131 | | |
132 | | - | |
133 | | - | |
134 | | - | |
135 | | - | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
136 | 137 | | |
137 | 138 | | |
138 | 139 | | |
| |||
Lines changed: 46 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
| 29 | + | |
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| |||
336 | 336 | | |
337 | 337 | | |
338 | 338 | | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
339 | 384 | | |
340 | 385 | | |
341 | 386 | | |
| |||
0 commit comments