Skip to content

fix: preserve attachment cancellation through storage errors - #2820

Draft
Rana Singh (ranadeepsingh) wants to merge 1 commit into
microsoft:masterfrom
ranadeepsingh:fix/attachment-cancellation-followup-20261109
Draft

Rana Singh (ranadeepsingh) wants to merge 1 commit into
microsoft:masterfrom
ranadeepsingh:fix/attachment-cancellation-followup-20261109

Conversation

@ranadeepsingh

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

Copy link
Copy Markdown
Collaborator

Attachment storage can wrap or clear interruption signals, causing a canceled Spark task to continue or return an ordinary row error. This follow-up preserves interruption through file reads and cleanup while keeping recognizable storage timeouts sanitized and row-local.

Related Issues/PRs

Follow-up to #2807 and #2801.

What changes are proposed in this pull request?

  • Check task/thread cancellation before and after attachment IO.
  • Recognize wrapped and suppressed interruption, including cyclic exception graphs, without treating timeout-typed causes as cancellation or replacing fatal errors.
  • Cover both legacy chat-completions and responses paths with local filesystem and HTTP fixtures; no live service calls.

Intentional limitation: a plain InterruptedIOException with no timeout-specific type in its cause chain is treated as interruption, even when the thread flag was cleared and Spark has not marked the task canceled. If a connector uses that same exception shape for a timeout, the error fails the task rather than becoming a row error; Spark may retry the task and repeat requests already sent by that task. Exception messages such as "timeout" or "deadline reached" are not used to guess the cause. The chosen policy preserves interruption semantics rather than risking swallowing a real interruption. Typed timeouts and wrappers retaining a recognizable timeout cause remain row-local unless there is an independent interruption or cancellation signal.

How is this patch tested?

Local validation covers the pending source corrections based on master 6c2699defcfb24d5bff5ba55f2252ba2d8cbea24. Those corrections are not yet all in the published PR head.

sbt "set cognitive / Test / fork := false" "cognitive/compile" "cognitive/Test/compile" "cognitive/testOnly com.microsoft.azure.synapse.ml.services.openai.OpenAIPromptMultimodalRequestSuite" "cognitive/scalastyle" "cognitive/Test/scalastyle"

Passed: compile, test compilation, 89/89 tests (0 skipped), production scalastyle, and test scalastyle. Run with JDK 8, Spark 3.5.0, Scala 2.12.17, and a single test JVM.

Draft status: local regression gates passed. The six-round review process, publication and Azure/GitHub CI for the latest pending source, and remote-comment reconciliation are not yet complete. Published as a draft first with explicit approval so review evidence can use the real PR number; no readiness gate is waived.

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

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:
- Check task/thread cancellation before and after attachment IO.
- Recognize wrapped and suppressed interruption, including cyclic exception graphs, without treating storage timeouts as cancellation or replacing fatal errors.
- Cover both legacy chat-completions and responses paths with local filesystem and HTTP fixtures; no live service calls.

Prompting intent:
Preserve reviewed follow-up fixes after the prerequisite PRs were merged, and complete current-source validation and review.

Linked sources:
Follow-up to microsoft#2807 and microsoft#2801.

Rationale:
Attachment storage can wrap or clear interruption signals, causing a canceled Spark task to continue or return an ordinary row error. This follow-up preserves cancellation through file reads and cleanup while keeping storage timeouts sanitized and row-local.

Local validation:
sbt "set cognitive / Test / fork := false" "cognitive/compile" "cognitive/Test/compile" "cognitive/testOnly com.microsoft.azure.synapse.ml.services.openai.OpenAIPromptMultimodalRequestSuite" "cognitive/scalastyle" "cognitive/Test/scalastyle"
Passed: 69 tests, 0 skipped, compile/Test compile, both scalastyle gates.

Publication:
Explicitly authorized draft-first bootstrap; formal reviews and current-head CI remain pending.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ba39157-c8dd-4adb-90e0-ff963a1e6733
@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 9, 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).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant