Skip to content

Handle concurrent XCom writes with savepoint and UPDATE fallback to avoid 409 - #69959

Open
nagasrisai wants to merge 15 commits into
apache:mainfrom
nagasrisai:fix/xcom-execution-api-concurrent-409
Open

Handle concurrent XCom writes with savepoint and UPDATE fallback to avoid 409#69959
nagasrisai wants to merge 15 commits into
apache:mainfrom
nagasrisai:fix/xcom-execution-api-concurrent-409

Conversation

@nagasrisai

@nagasrisai nagasrisai commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Closes #69956

Summary

When two task runners (concurrent execution or task retry) write the same XCom key at roughly the same time, both call XComModel.set which does a DELETE followed by an INSERT. Both DELETEs succeed (they each see the record that was just written by the peer or see nothing), then both try to INSERT the same primary key. The second INSERT hits the unique constraint and the Execution API converts the IntegrityError to an HTTP 409, causing the task to fail.

Fix

Wrap the XComModel.set call in a savepoint (session.begin_nested()) so that a constraint violation only rolls back the XCom write and not any earlier work in the same request (e.g. the task_map merge). The IntegrityError is caught and handled with an explicit UPDATE that overwrites the existing entry with the latest value, which is the correct semantic for a retry.

try:
    with session.begin_nested():
        XComModel.set(...)
except IntegrityError:
    # concurrent write already committed; overwrite with latest value
    session.execute(update(XComModel).where(...).values(value=value, dag_result=dag_result))

Changes

  • airflow-core/src/airflow/api_fastapi/execution_api/routes/xcoms.py
    • Add update to the sqlalchemy import
    • Add IntegrityError import from sqlalchemy.exc
    • Wrap XComModel.set in session.begin_nested() and catch IntegrityError with an UPDATE fallback

Important

🛠️ Maintainer triage note for @nagasrisai · by @potiuk · 2026-07-28 16:11 UTC

Helpful heads-up from the maintainers — please address before this PR can be reviewed:

  • Pre-commit / static checks. See docs.
  • Unresolved review comments: 2 thread(s). See docs.

The ball is in your court — you've been assigned to this PR. Fix the above, then mark it Ready for review.

See the Pull Request quality criteria for how to fix each item. There is no rush.

Note: your branch is 270 commits behind main — please rebase and push again to get up-to-date CI results.

Automated triage — may be imperfect; a maintainer takes the next look. We use this two-stage triage process so maintainers' limited time goes to the conversation with you.

nagasrisai added a commit to nagasrisai/airflow that referenced this pull request Jul 16, 2026
@potiuk

potiuk commented Jul 20, 2026

Copy link
Copy Markdown
Member

@nagasrisai This PR has a few issues that need to be addressed before it can be reviewed — please see our Pull Request quality criteria.

Issues found:

  • Pre-commit / static checks: Failing: CI image checks / Static checks. Run prek run --from-ref main --stage pre-commit locally to reproduce and fix.

Note: Your branch is 51 commits behind main. Some check failures may be caused by changes in the base branch rather than by your PR. Please rebase your branch and push again to get up-to-date CI results.

What to do next:

  • Fix each issue listed above.
  • Make sure static checks pass locally (prek run --from-ref main --stage pre-commit).
  • Mark the PR as "Ready for review" when you're done.

There is no rush — take your time and work at your own pace. We appreciate your contribution and are happy to wait for updates. If you have questions, feel free to ask on the Airflow Slack.


Note: This comment was drafted by an AI-assisted triage tool and may contain mistakes. Once you have addressed the points above, an Apache Airflow maintainer — a real person — will take the next look at your PR. We use this two-stage triage process so that our maintainers' limited time is spent where it matters most: the conversation with you.

Comment thread airflow-core/src/airflow/api_fastapi/execution_api/routes/xcoms.py Outdated
Comment thread airflow-core/src/airflow/api_fastapi/execution_api/routes/xcoms.py
@potiuk
potiuk marked this pull request as draft July 28, 2026 16:11
Catching all IntegrityError was too broad: a FK violation (e.g. the
task_instance cascade-deleted between the dag_run_id lookup and the
flush) would also land here, causing the fallback UPDATE to match
zero rows while still returning 200 — silently losing the write.

Narrow the guard to unique-constraint messages per dialect
(matching the pattern in _UniqueConstraintErrorHandler) and re-raise
everything else.
@nagasrisai

nagasrisai commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@kaxil - Thanks for the pointers! I've pushed two follow-up commits:

  1. Narrowed the except IntegrityError guard to unique-constraint violations only (matching the per-dialect strings in _UniqueConstraintErrorHandler) so FK violations propagate correctly instead of being silently swallowed.
  2. Added two tests to TestXComsSetEndpoint — one that exercises the UPDATE fallback path by patching XComModel.set to raise a unique-constraint error, and one that confirms FK errors propagate as a 500.

Will also look into getting the static checks clean.

@potiuk

…m_set

Adds two tests to TestXComsSetEndpoint:

* test_xcom_set_concurrent_write_uses_update_fallback — pre-seeds the
  row, patches XComModel.set to raise a unique-constraint IntegrityError
  once, and asserts the endpoint returns 201 with the latest value
  stored via the UPDATE fallback.

* test_xcom_set_fk_integrity_error_propagates — patches XComModel.set
  to raise an FK IntegrityError and asserts it propagates as a 500
  rather than being silently swallowed.
@nagasrisai
nagasrisai marked this pull request as ready for review August 5, 2026 03:33
@nagasrisai nagasrisai changed the title fix: handle concurrent XCom writes with savepoint + UPDATE fallback to avoid 409 Handle concurrent XCom writes with savepoint and UPDATE fallback to avoid 409 Aug 8, 2026
@nagasrisai

Copy link
Copy Markdown
Contributor Author

@potiuk - Could you please mark this PR as ready for review? It's currently waiting for a reviewer. Thanks!

CC @kaxil

@nagasrisai
nagasrisai requested a review from kaxil August 17, 2026 06:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Concurrent/retried Execution API XCom writes fail with 409 due to duplicate primary key

3 participants