GertL opened a new pull request, #74568:
URL: https://github.com/apache/airflow/pull/74568

   A fan-out partition mapper can turn one asset event into up to 
`partition_mapper_max_downstream_keys` downstream keys per target Dag (default 
1000, and a mapper may set its own higher `max_downstream_keys`). 
`_queue_partitioned_dags` called `_get_or_create_apdr` once per key, and each 
call:
   
   - re-took the `AssetModel` row lock (`SELECT ... FOR KEY SHARE`, or a no-op 
`UPDATE` + flush on SQLite),
   - ran its own "latest APDR for this key" query,
   - flushed after creating or updating the APDR.
   
   That is 2–4 round trips per key, all inside one transaction while the lock 
is held. The `AssetModel` row was also re-selected for every target Dag, 
although `asset_id` does not change inside the loop.
   
   ### Change
   
   - New `AssetManager._get_or_create_apdrs(target_keys=...)` resolves every 
key of a target Dag in one pass:
     - takes the `AssetModel` lock once (a row lock is held until the 
transaction ends, so re-taking it per key added nothing),
     - reads the newest APDR of every key in one query (`max(id)` grouped by 
`partition_key`), chunked at 500 keys to stay under SQLite's bound-parameter 
limit,
     - adds new APDRs and flushes once, so their ids are available for the 
`PartitionedAssetKeyLog` rows.
   - Results are returned in key order, and a key repeated in the list resolves 
to the same APDR, matching the previous one-at-a-time behaviour.
   - The `partition_date` reconciliation rules (adopt when none, suppress on 
conflict, keep when agreeing) are unchanged.
   - `_get_or_create_apdr` is kept as a single-key wrapper, so its existing 
tests, including the concurrent-creation race test, run unchanged.
   - `_queue_partitioned_dags` loads the `AssetModel` once instead of once per 
target Dag.
   
   ### Effect
   
   Resolving existing keys, measured with `count_queries` against the previous 
implementation:
   
   | keys | before | after |
   |---|---|---|
   | 10 | 20 | 2 |
   | 200 | 400 | 2 |
   
   (The previous implementation also flushed once per key.)
   
   ### Tests
   
   - `test_get_or_create_apdrs_reuses_pending_and_dedupes_in_order`: key order, 
reuse of a pending APDR, repeated keys.
   - `test_get_or_create_apdrs_query_count_does_not_grow_with_keys`: resolving 
200 existing keys costs the same number of queries as resolving 2.
   - Existing `tests/unit/assets/test_manager.py` passes (60 tests), as do the 
partition and asset tests in `test_scheduler_job.py`, `test_taskinstance.py`, 
`test_partitioned_dag_runs.py` and the partition mapper tests. Run locally on 
SQLite only; the Postgres/MySQL row-lock path is left to CI.
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes (please specify the tool below)
   
   **Enola**: enola provided all the insights 
https://github.com/enola-labs/enola
   Generated-by: Claude Code following [the 
guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to