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

   `order_by=rendered_map_index` on the `listMapped` and `listTaskInstances` 
endpoints had two bugs:
   
   1. **Retried TIs silently pushed off the first page** — when 
`_rendered_map_index` was NULL for all rows (no `map_index_template`), the sort 
fell through to the UUID tiebreaker. Retried TIs receive a new UUID at retry 
time (a larger, later timestamp), so they sorted to the end of the result set 
and fell outside `LIMIT N`. Already partially addressed by #66008, which added 
the SQL `.expression` fallback `CAST(map_index AS String)`.
   
   2. **Lexicographic ordering for 10+ mapped instances** — the `CAST(map_index 
AS String)` fallback produces string comparison: `"10"` sorts before `"2"`, 
`"20"` before `"3"`, etc. A Dag with 12 mapped tasks returned them as `0, 1, 
10, 11, 2, 3 …` instead of `0, 1, 2, 3 … 10, 11`.
   
   closes: #67451
   
   ## Root cause
   
   `SortParam` resolved `rendered_map_index` to a single column for `ORDER BY`. 
With a nullable primary column and a string-cast fallback, there was no stable 
integer secondary key, so UUID ordering determined page membership for tasks 
without `map_index_template`.
   
   ## Fix
   
   Extend `SortParam.to_replace` to accept `list[Column]` as a **compound 
sort**: a single user-facing sort key expands into multiple `ORDER BY` columns. 
Both `listMapped` and `listTaskInstances` now map `rendered_map_index` to 
`[TI._rendered_map_index, TI.map_index]`,producing:
   
   ```sql
   ORDER BY _rendered_map_index ASC,   -- NULL when no map_index_template
            map_index            ASC,  -- integer, always present
            id                   ASC   -- UUID, absolute tiebreaker
   ```
   
   | Scenario | Result |
   |---|---|
   | No `map_index_template` (common case) | All `_rendered_map_index` NULL → 
tie on key 1 → sorted by integer `map_index` → `0, 1, 2, 10, 11 …` |
   | With `map_index_template` | Sorted alphabetically by custom label, then 
`map_index` for ties |
   | Retried TI (newer UUID, same `map_index`) | UUID is last tiebreaker only — 
no longer pushed off the first page |
   
   ## Changes
   
   **`airflow/api_fastapi/common/parameters.py`**
   
   - `SortParam.__init__` type annotation extended: `dict[str, str | Column | 
list[Column]] | None`
   - `SortParam._resolve()` — when a `to_replace` value is a `list`, each 
column is expanded into its own sort entry using the column's ORM
     `.key` as `attr_name`, so `row_value()` resolves it via `getattr` without 
any additional lookup.
   - `SortParam.row_value()` — guard updated to skip list-form values (they are 
already expanded in `_resolve()`).
   
   **`airflow/api_fastapi/core_api/routes/public/task_instances.py`**
   
   - `listMapped` and `listTaskInstances` `SortParam` both gain  
`"rendered_map_index": [TI._rendered_map_index, TI.map_index]` in their 
`to_replace` dicts.
   
   ## Tests
   
   - Updated the two `rendered_map_index` / `-rendered_map_index` cases in the 
existing `test_mapped_instances_order` parametrize to expect numeric order 
(`list(range(100))` / `list(range(109, 9, -1))`) instead of the previous 
lexicographic expectations (`sorted(range(110), key=str)`).
   - **New** `test_rendered_map_index_order_with_template`: verifies that when 
all TIs have a custom `_rendered_map_index` label the sort is alphabetical by 
label.
   - **New** `test_rendered_map_index_order_retried_tis_not_displaced`: 
simulates retries by assigning newer UUIDs to some TIs and verifies all TIs 
still appear on the first page in `map_index` order.
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes — Claude Code (claude-sonnet-4-6)
   
   Generated-by: Claude Code (claude-sonnet-4-6) 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