kaxil commented on code in PR #74528:
URL: https://github.com/apache/airflow/pull/74528#discussion_r4501658756


##########
providers/standard/src/airflow/providers/standard/sensors/external_task.py:
##########
@@ -378,16 +392,34 @@ def _get_count(states: list[str]) -> int:
         if self.failed_states:
             count = _get_count(self.failed_states)
             count_failed = self._calculate_count(count, dttm_filter)
+            if count_failed > 0:

Review Comment:
   Nothing pins these guards. Making this push unconditional, doing the same 
for `count_skipped`, or moving the success push above the `return False` all 
keep the test file green, since every V3 test ends the wait on the first poke 
and the `ti` from `setup_method` is an unspecced `MagicMock`. Could you add a 
V3 case where the counts are 0 and assert `poke()` returns False without 
calling `get_task_states` or `xcom_push`?



##########
providers/standard/src/airflow/providers/standard/sensors/external_task.py:
##########
@@ -65,6 +67,13 @@
 
     from airflow.providers.common.compat.sdk import Context, TaskInstanceKey
 
+XCOM_EXTERNAL_RUN_IDS = "external_run_ids"
+
+
+def _build_airflow_ui_url(path: str) -> str:

Review Comment:
   This is core's `build_airflow_dagrun_url` with the path left open. Could 
`get_link` use it for the single-run case too 
(`f"dags/{external_dag_id}/runs/{run_id}"`) and drop the 
`airflow.utils.helpers` import?



##########
providers/standard/src/airflow/providers/standard/sensors/external_task.py:
##########
@@ -378,16 +392,34 @@ def _get_count(states: list[str]) -> int:
         if self.failed_states:
             count = _get_count(self.failed_states)
             count_failed = self._calculate_count(count, dttm_filter)
+            if count_failed > 0:
+                self._push_external_run_ids(context, dttm_filter)
             self._handle_failed_states(count_failed)
 
         if self.skipped_states:
             count = _get_count(self.skipped_states)
             count_skipped = self._calculate_count(count, dttm_filter)
+            if count_skipped > 0:
+                self._push_external_run_ids(context, dttm_filter)
             self._handle_skipped_states(count_skipped)
 
         count = _get_count(self.allowed_states)
         count_allowed = self._calculate_count(count, dttm_filter)
-        return count_allowed == len(dttm_filter)
+        if count_allowed != len(dttm_filter):
+            return False
+        self._push_external_run_ids(context, dttm_filter)
+        return True
+
+    def _push_external_run_ids(self, context: Context, dttm_filter: 
Sequence[datetime.datetime]) -> None:

Review Comment:
   This runs ahead of the outcome: before `_handle_failed_states` / 
`_handle_skipped_states` raise, before `return True`, and before 
`execute_complete` reads the event. So if the extra `get_task_states` call or 
the XCom push fails, the link decides the task state. A `soft_fail=True` sensor 
that hit `failed_states` fails instead of skipping, and a sensor whose upstream 
succeeded fails or retries. `finalize()` wraps `get_link` in a `try/except` so 
a link can't fail the task. Could this catch `Exception` and log a warning, so 
a failed lookup only costs the link? `get_link` already falls back to the Dag 
page when the key is missing.



-- 
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