1fanwang opened a new pull request, #71518:
URL: https://github.com/apache/airflow/pull/71518
Operator extra links are cached as XCom rows under the link's `xcom_key`,
which carries no
attempt. `XComOperatorLink.get_link` receives a `TaskInstanceKey` and
ignores its
`try_number`, so once a task retries, asking for an earlier attempt's link
hands back the
latest attempt's URL.
#65661 made the extra-links endpoint resolve the requested attempt, which is
what makes the
wrong answer reachable: the UI can now ask for attempt 1 and gets attempt
2's link, pointing
at the wrong logs. The retry also clears the task's XComs, so nothing older
survives to
resolve against.
It matters most when the URL cannot be recomputed — a job id the remote
service mints per
submission, so each attempt gets a different one. Providers linking to
per-attempt logs in
EMR, Glue, Databricks, Dataproc and Livy are all in this shape.
The worker now also caches the link under a key carrying the attempt that
produced it, and
the reader prefers that row, falling back to the bare key so links written
before this
change still resolve. Those rows are exempt from the clear a retry issues,
since they
describe attempts that already ran. The prefix is owned by Airflow rather
than derived from
the link's `xcom_key`, because a link may override that with any name, as
the Databricks and
Google links do.
This is one of the shapes I floated on the issue and the smallest I could
find. Happy to
rework it if you would rather give `xcom_key` access to `ti_key`, or put
links on the task
state store alongside the durable-execution work in #69914 and #71211.
closes: #71471
## Testing
The regression is in `XComOperatorLink.get_link`, so I ran that class
against a real
metastore with three rows — attempt 1's link, attempt 2's link, and the bare
key — asking it
for each attempt, before and after the change.
<details><summary>Raw output</summary>
Before, on 3.2.2. Attempt 1 resolves to attempt 2's URL:
```
$ python read_test.py
try 1 -> https://logs/attempt-2
try 2 -> https://logs/attempt-2
```
After:
```
$ python read_test.py
try 1 -> https://logs/attempt-1
try 2 -> https://logs/attempt-2
```
The purge predicate was checked separately against a table of keys,
including ones that
would be spared if the `_` in the prefix were left as a LIKE wildcard:
```
spared : ['_link_attempt_1__link_Foo',
'_link_attempt_2_databricks_job_run_link']
cleared: ['_link_Foo', 'databricks_job_run_link', 'return_value',
'Xlink_attemptX1_y', 'my_link_attempt_1_thing']
```
</details>
Added tests cover all three sides: the reader prefers the requested attempt
and falls back
to the bare key, and the run endpoint keeps the per-attempt rows out of
`xcom_keys_to_clear`. I could not run the suite locally, so I am relying on
CI for it.
--
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]