Uh oh!
There was an error while loading. Please reload this page.
AIP-103: Setting up foundation with ORM and Backend Abstraction - #65759
Conversation
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
amoghrajesh
commented
Apr 29, 2026
@jscheffl@jroachgolf84@ashb do you wanna take another look? Planning to merge it once CI is green otherwise |
amoghrajesh
commented
Apr 29, 2026
Rerunning with full tests |
amoghrajesh
commented
Apr 30, 2026
The failure: https://github.com/apache/airflow/actions/runs/25119239062/job/73621449539?pr=65759 was intermittent, retriggered that job |
amoghrajesh
commented
Apr 30, 2026
Thanks for reviews folks, merging this one in, I handled all comments and resolved it, but if you think you need some changes to be done, let me know, I can take it as a follow up |
Uh oh!
There was an error while loading. Please reload this page.
…he#65759) * Adding ORM models for task_state and asset_state * Adding base state backend and metastore implementation * Introducing config: [state_store]
Was generative AI tooling used to co-author this PR?
AIP-103 PR 1: DB Schema + Backend Abstraction
This PR lays the foundation for AIP-103 (Task State Management) — a key-value state store scoped to task instances and assets. It implements the DB layer, the backend abstraction, and config — everything needed to persist and retrieve state before any API or SDK work begins.
closes: #65777
What's in this PR
1. ORM Models
Two new models:
TaskStateModelandAssetStateModelinairflow/models/.task_statePK is(dag_run_id, task_id, map_index, key):dag_run_idis an integer FK todag_run.idwith CASCADE DELETE — task state is automatically wiped when a run is deleted, no orphan cleanup job needed.dag_idandrun_idare denormalized strings alongsidedag_run_id. The integer FK is for the JOIN and CASCADE; the strings are for fast Execution API lookups without a join and for surfacingupdated_by_runin the Core API response.map_index(default-1) gives each mapped task instance its own namespace. Without it, all instances of the same mapped task share one row per key — instance 0 writesremote_job_id=app_001, instance 1 overwrites it withapp_002, instance 0 retries and reconnects to the wrong job.asset_statePK is(asset_id, key):asset_idFK toasset.idwith CASCADE DELETE.dag_run_id— asset state is intentionally run-independent. A watermark written in run 1 is readable by run 2. This is what distinguishes it from task state.Two tables instead of one because the GC lifecycles, index shapes, and FK targets are entirely different for the two scopes. A single discriminated table would mean permanently null columns on every row and would conflate two very different cleanup models.
What the schema implies:
(dag_run_id, task_id, map_index)will have same rows. Try 3 readsremote_job_idwritten by previous try and reconnects. This is the core AIP-103 use case.2. Alembic Migration
Migration
0112_3_3_0_add_task_state_and_asset_statecreates both tables.3. BaseStateBackend in
shared/stateTaskScope,AssetScope,StateScope, andBaseStateBackendlive in a new shared distribution (apache-airflow-shared-state) rather thanairflow-core. This is the only placement that avoids circular dependencies across all three consumers: provider packages (e.g. S3/GCS custom backends) cannot depend onairflow-core;task-sdkneeds the scope dataclasses for context accessors in PR 3;airflow-coreneeds them forMetastoreStateBackend.The interface takes a single
scopeparameter — the backend routes internally onisinstance(scope, TaskScope). All eight methods (four sync, four async) are abstract — implementation must provide real async code. Async variants are required for AIP-98 compatibility so async tasks can callawait task_state.aset(...)without blocking the event loop.The
[state]config section (backendkey) andresolve_state_backend()follow theresolve_xcom_backend()pattern — validate the configured class is aBaseStateBackendsubclass before returning it.4. MetastoreStateBackend
Default implementation in
airflow/state/metastore.py. Routes on scope type, resolvesdag_run_idfrom(dag_id, run_id)before writing task state, and follows the standard@provide_sessionpattern throughoutairflow-core.Next steps
{pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.