Skip to content

fix: honor the assigned Spark session for complex Params - #2809

Merged
Rana Singh (ranadeepsingh) merged 2 commits into
microsoft:masterfrom
ranadeepsingh:fix/complex-params-session-20261105
Nov 9, 2026
Merged

Rana Singh (ranadeepsingh) merged 2 commits into
microsoft:masterfrom
ranadeepsingh:fix/complex-params-session-20261105

Conversation

@ranadeepsingh

@ranadeepsingh Rana Singh (ranadeepsingh) commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

Selecting an MLReader or MLWriter Spark session currently does not consistently select the session used for complex payloads. Serializer policy and filesystem configuration can therefore come from a different active session. This propagates the assigned session through the payload helpers.

Related Issues/PRs

Fixes #2803.

Extracted from the scope refinement for #2759. This fix is independent of the native feature and optional recovery work.

What changes are proposed in this pull request?

Add session-bearing helper overloads and retain the existing signatures and serialized format. Test writer session selection and both directions of the existing legacy-deserialization opt-in through public UDFTransformer reads. Also exercise the retained three-argument helpers with active-session selection and default-session fallback, checking both the selected session and the saved/restored payload. Do not change global deserialization defaults or add native-AI persistence.

This fixes the direct complex-payload helper boundary. It does not claim recursive session propagation through nested Spark Pipeline stages or transfer ownership of a DataFrame's write session.

How is this patch tested?

  • I have written tests (not required for typo or doc fix) and confirmed the proposed feature/bug-fix/change works.

All three relevant baseline regressions failed: the writer used the wrong session, and both assigned-reader policy directions behaved incorrectly. All three passed with the fix.

The original SBT commands below ran with the branch-selected JDK on baseline d3f3af6bd3e4b7d191f51c9eb29f9aeffe788193 plus the five isolated prerequisite fixes, without AIPrompt feature code. The production implementation remains byte-identical to that tested implementation. Those original five fixes were tested together; the later isolated validation below covers this PR separately, including the two added compatibility tests. Current-head CI is tracked separately.

Baseline: sbt "core/testOnly com.microsoft.azure.synapse.ml.param.VerifyGlobalParams com.microsoft.azure.synapse.ml.core.serialize.ValidateComplexParamSerializer com.microsoft.azure.synapse.ml.stages.VerifyUDFTransformerPersistence com.microsoft.azure.synapse.ml.codegen.PyCodegenSuite com.microsoft.azure.synapse.ml.io.split1.VerifyResponseBodyInspection -- -z \"concurrent global\" -z \"assigned Spark session\" -z \"generated additional method stubs\" -z \"response conversion closes\"" - 7 expected failures across the extracted core regressions with unchanged baseline production.

Fixed: sbt "core/testOnly com.microsoft.azure.synapse.ml.param.VerifyGlobalParams com.microsoft.azure.synapse.ml.param.GlobalParamSuite com.microsoft.azure.synapse.ml.core.serialize.ValidateComplexParamSerializer com.microsoft.azure.synapse.ml.stages.VerifyUDFTransformerPersistence com.microsoft.azure.synapse.ml.codegen.PyCodegenSuite com.microsoft.azure.synapse.ml.io.split1.VerifyResponseBodyInspection" - 52 passed, none canceled or ignored.

sbt core/scalastyle core/Test/scalastyle - passed, zero errors/warnings.

Additional isolated validation for 88b559e794b18a87af0d969edf17b16a84536cbe, using JDK 11 on the master baseline:

  • sbt core/compile core/Test/compile - passed.
  • sbt "core/testOnly com.microsoft.azure.synapse.ml.core.serialize.ValidateComplexParamSerializer com.microsoft.azure.synapse.ml.stages.VerifyUDFTransformerPersistence" - 15/15 passed, zero failed, aborted, canceled, ignored, or pending tests.
  • sbt core/scalastyle core/Test/scalastyle - passed, zero errors/warnings.
  • The same two new legacy-overload compatibility cases, run against the exact-base serializer classpath overlay - 2/2 passed, confirming that they protect retained behavior rather than require the new overloads.
  • Prior independent exact-base comparison confirmed seven direct assigned-session failures fixed. No production code, serialization format, dependency, or public JVM descriptor changed in this test-only follow-up.

Does this PR change any dependencies?

  • No. You can skip this section.
  • Yes. Make sure the dependencies are resolved correctly, and list changes here.

Does this PR add a new feature? If so, have you added samples on website?

  • No. You can skip this section.
  • Yes. Make sure you have added samples following below steps.
  1. Find the corresponding markdown file for your new feature in website/docs/documentation folder.
    Make sure you choose the correct class estimators/transformers and namespace.
  2. Follow the pattern in markdown file and add another section for your new API, including pyspark, scala (and .NET potentially) samples.
  3. Make sure the DocTable points to correct API link.
  4. Navigate to website folder, and run npm start to make sure the website renders correctly.
  5. Don't forget to add <!--pytest-codeblocks:cont--> before each python code blocks to enable auto-tests for python samples.
  6. Make sure the WebsiteSamplesTests job pass in the pipeline.

## Summary
Pass the MLReader or MLWriter session into complex parameter serialization
and deserialization. Retain the existing helper overloads and stored format.
Cover writer selection and both directions of reader deserialization policy.

## Prompting Intent
Separate unrelated persistence repairs from the native AIPrompt feature.
Prove that a caller-selected Spark session governs complex payload handling
rather than inheriting an unrelated active session's configuration.

## Linked Sources
- Bug: microsoft#2803
- Scope: microsoft#2759

## Rationale
Threading the already assigned session through overloads fixes the actual
boundary without changing global Spark state, serialized parameter shapes or
unsafe-deserialization defaults. The three regressions failed on baseline and
passed with the existing serialization and UDF persistence suites.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ba39157-c8dd-4adb-90e0-ff963a1e6733
Copilot AI balanced review requested due to automatic review settings November 5, 2026 10:01
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown

Hey Rana Singh (@ranadeepsingh) 👋!
Thank you so much for contributing to our repository 🙌.
Someone from SynapseML Team will be reviewing this pull request soon.

We use semantic commit messages to streamline the release process.
Before your pull request can be merged, you should make sure your first commit and PR title start with a semantic prefix.
This helps us to create release messages and credit you for your hard work!

Examples of commit messages with semantic prefixes:

  • fix: Fix LightGBM crashes with empty partitions
  • feat: Make HTTP on Spark back-offs configurable
  • docs: Update Spark Serving usage
  • build: Add codecov support
  • perf: improve LightGBM memory usage
  • refactor: make python code generation rely on classes
  • style: Remove nulls from CNTKModel
  • test: Add test coverage for CNTKModel

To test your commit locally, please follow our guild on building from source.
Check out the developer guide for additional guidance on testing your change.

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues were identified for the changes to honor assigned Spark sessions during complex parameter persistence.

No open issues 🎉

What changed in this PR

This PR makes complex parameter persistence honor the Spark session assigned to an MLReader or MLWriter, keeping payload handling consistent with metadata handling.

Changes:

  • Pass the assigned session through complex payload helpers using new overloads, preserving existing signatures and serialized formats.
  • Add a writer-session regression test with a payload round-trip check.
  • Test both allowed and denied legacy deserialization through public UDFTransformer reads when assigned and active session policies differ.
File Description
core/​src/​test/​scala/​com/​microsoft/​azure/​synapse/​ml/​stages/​VerifyUDFTransformerPersistence.scala Tests assigned-reader deserialization policy in both directions.
core/​src/​test/​scala/​com/​microsoft/​azure/​synapse/​ml/​core/​serialize/​ValidateComplexParamSerializer.scala Verifies assigned-writer session selection and payload round-trip.
core/​src/​main/​scala/​org/​apache/​spark/​ml/​ComplexParamsSerializer.scala Propagates assigned sessions through new, backward-compatible helper overloads.

Review effort: Balanced

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

CI triage: the train execution reports 78/78 passing tests; the R LightGBM runtime also completed. Test-result and coverage publication then failed with a TLS hostname mismatch, tracked in #2812. The missing named train/R outcomes are not counted as verified passes, even where the publication task badge is green. Required CI remains blocked; no product workaround or blind full-build rerun was made.

## Summary
Exercise the retained three-argument save/load helpers with active-session
selection and default-session fallback. Check selected-session markers during
both serialization and deserialization and verify the restored byte payload.

## Prompting Intent
Make the necessary minor fixes to the reviewed SynapseML PRs, address review
feedback, and verify full CI against each final head without merging.
Close the identified compatibility-test gap without expanding production scope.

## Linked Sources
- PR: microsoft#2809
- Issue: microsoft#2803
- Existing regression suite: core/src/test/scala/com/microsoft/azure/synapse/ml/core/serialize/ValidateComplexParamSerializer.scala

## Rationale
Keep the compatibility contract executable rather than relying solely on JVM
descriptor checks and external review probes. A small Spark-package test bridge
accesses the private[ml] helpers without changing production visibility.
Restore prior session state in finally and retain the shared SparkContext.
Both new cases pass on the exact base implementation, confirming retained
behavior; the relevant current suites pass 15/15 with no skipped tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0e8fdfb7-dcdd-4074-aabb-8634695107f2
Copilot AI balanced review requested due to automatic review settings November 8, 2026 13:53
@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues are recorded for the change to honor assigned Spark sessions during complex-parameter persistence.

No open issues 🎉

Review effort: Balanced

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

CI triage for head 88b559e794b18a87af0d969edf17b16a84536cbe: Azure build 245525539 published 12/12 passing serializer tests and 3/3 passing UDF persistence tests, with no skipped cases. Both new legacy-helper compatibility cases have named Passed outcomes.

The only failed job was PythonTests cognitive, in Install and package deps. Its Python test and result-publication steps were abandoned. Azure supplied neither a task log nor an error message for that failed step, so the exact cause is unconfirmed; the missing Python outcomes are not counted as passes.

Requested a retry of that single failed job on the same build and exact source/target, retaining the original attempt evidence. No product, dependency, or pipeline change was made. Full CI remains pending until this job completes and its named Python results are verified.

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.99%. Comparing base (d3f3af6) to head (88b559e).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #2809   +/-   ##
=======================================
  Coverage   87.99%   87.99%           
=======================================
  Files         347      347           
  Lines       21608    21608           
  Branches     2297     2282   -15     
=======================================
  Hits        19015    19015           
  Misses       2593     2593           
Files with missing lines Coverage Δ
.../org/apache/spark/ml/ComplexParamsSerializer.scala 98.36% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

Engineering readiness verified for 88b559e794b18a87af0d969edf17b16a84536cbe, based on current master d3f3af6bd3e4b7d191f51c9eb29f9aeffe788193.

The test-only follow-up now exercises both retained three-argument persistence helpers: active-session selection and default-session fallback, including session markers during save/load and restored payload equality. No production signature, serialized format, or dependency changed. The PR description was updated without replacing its template.

  • Local compile and main/test Scala style passed; the two relevant suites 15/15 passed. Both new compatibility cases also passed 2/2 on the exact-base serializer overlay, proving retained behavior.
  • Azure build 245525539 succeeded. Named serializer results are 12/12, including both new cases; UDF persistence results are 3/3, with no skipped cases.
  • The Python cognitive setup job recovered on its isolated retry: 165/165 named Python tests passed, and test/coverage publication succeeded. The original unlogged setup failure's cause remains unconfirmed; no code or CI workaround was introduced.
  • Codecov now reports 100% patch coverage and all modified coverable lines covered, closing the previous compatibility-overload coverage gap.
  • No previously published suite disappeared. The 22 non-executed outcomes match the prior passing build's per-suite counts.
  • Current-head review is clean, with zero unresolved threads or suppressed findings; all required checks are green, and the branch is not behind master.

Scope remains the direct complex-payload boundary, not recursive nested-Pipeline session propagation or changing a DataFrame's owning session. Only the required human approval remains; the PR has not been merged.

@ranadeepsingh
Rana Singh (ranadeepsingh) merged commit 2f3d9cc into microsoft:master Nov 9, 2026
77 checks passed
Bora Elkin (BoraElkin) pushed a commit to BoraElkin/SynapseML that referenced this pull request Nov 9, 2026
AB#5837660

## Summary
Add a combined persistence regression after integrating the latest master fixes.
Verify that an explicitly assigned Spark session is used without promoting
default scalar parameters into explicit values. Preserve the historical review
archive through rebased links and include the focused integration review.

## Prompting Intent
The engineer approved resolving the newly introduced merge conflicts without
losing either CU behavior or upstream fixes, validating and reviewing the
result, publishing with an explicit force-with-lease, and rerunning CI.

## Linked Sources
- Feature PR: microsoft#2815
- Python method extraction: microsoft#2810
- Assigned Spark sessions: microsoft#2809
- Response cleanup: microsoft#2808
- Attachment cancellation: microsoft#2807
- Global parameter synchronization: microsoft#2806
- Integration target: 6c2699d
- Focused review: reviews/pr-2815/task-5837660-attempt-10-review-0-harness.md

## Rationale
Keep both sides of the code-generation and persistence conflicts rather than
choosing one wholesale. A combined public save/load test checks the interaction
that independent upstream and CU tests do not explicitly cover. Rebase preserves
the six original changes and their messages; all 53 archived report blobs and
modes are unchanged. Local validation passed 310 Scala and 73 Python tests,
with one existing ignored global-fuzzing test, plus style, compilation, codegen
and pinned formatting. New-head CI remains a separate post-publication gate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 653e4257-0554-408f-9e0e-b23750249edb
Rana Singh (ranadeepsingh) added a commit to ranadeepsingh/SynapseML that referenced this pull request Nov 9, 2026
## Summary
Add direct coverage for the existing no-argument and null-session serializer
fallback, including active/default session preservation, and retain the
independent review evidence. No production behavior changes in this commit.

## Prompting Intent
Complete validation, independent reviews, CI and comment reconciliation for
the remaining SynapseML pull requests after the prerequisites were merged.
Preserve legacy behavior and public signatures; do not merge any pull request.

## Linked Sources
- microsoft#2818
- microsoft#2809
- microsoft#2803
- reviews/pr-2818/task-unknown-attempt-11-stage-attempt-1-review-3-grok-4.7-slice1.md
- reviews/pr-2818/task-unknown-attempt-11-stage-attempt-1-review-6-grok-4.7-slice1.md

## Rationale
Keep fallback behavior covered at the public serializer boundary rather than
changing it in response to an incorrect baseline assumption. The baseline and
current runtime agree in 18 absent-session cases; review rebuttals preserve
the original findings and document this evidence.

## Validation
sbt "set core / Test / fork := false" "core/compile" "core/Test/compile" "core/testOnly com.microsoft.azure.synapse.ml.core.serialize.ValidateComplexParamSerializer com.microsoft.azure.synapse.ml.stages.VerifyUDFTransformerPersistence" "core/scalastyle" "core/Test/scalastyle"
Passed: 31 tests, 0 skipped, production/test compilation and both style gates.
Six independent three-family review rounds completed with explicit dispositions.
New-head CI, remote-comment reconciliation and the final CI-qualified review
remain separate gates; the pull request remains a draft.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ba39157-c8dd-4adb-90e0-ff963a1e6733
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: honor the assigned Spark session for complex Params persistence

4 participants