potiuk commented on code in PR #68792:
URL: https://github.com/apache/airflow/pull/68792#discussion_r3680753521


##########
airflow-core/src/airflow/jobs/triggerer_job_runner.py:
##########
@@ -720,6 +723,21 @@ def clean_unused(self) -> None:
         """Remove triggers that are no longer needed."""
         Trigger.clean_unused()
 
+    def check_for_unhandled_triggers(self, num_running: int) -> None:
+        """
+        Shut down if the subprocess trigger count disagrees with the 
supervisor.
+
+        Only valid between finished-removal and to_create-addition in 
``_handle_request``.
+        """
+        expected = len(self.running_triggers)
+        if expected != num_running:
+            log.error(
+                "Trigger count mismatch: expected %d, subprocess reports %d. 
Shutting down.",
+                expected,
+                num_running,
+            )
+            self.stop = True

Review Comment:
   This exits the supervisor loop via `should_stop()`, terminating the 
Triggerer and every trigger it is running. The tasks get picked up by another 
Triggerer eventually, so it's recoverable — but it's a disruptive, 
whole-process response to what may be a transient accounting difference.
   
   The docstring concedes the invariant is only valid "between finished-removal 
and to_create-addition", which is a timing-dependent window: `num_running` is 
computed in the subprocess when it builds the message, and compared against 
supervisor state some time later. I'd want to see the argument for why no 
legitimate interleaving can produce a one-off difference before wiring it to a 
shutdown.
   
   Softer options that still surface the bug: log at ERROR and emit a metric, 
or require N consecutive mismatches before stopping so a single transient blip 
doesn't cost an outage. If shutdown really is the right call, a comment 
explaining why the window is airtight would help the next reader.
   
   ---
   Drafted-by: Claude Code (Opus 5); reviewed by @potiuk before posting



##########
airflow-core/src/airflow/jobs/triggerer_job_runner.py:
##########
@@ -720,6 +723,21 @@ def clean_unused(self) -> None:
         """Remove triggers that are no longer needed."""
         Trigger.clean_unused()
 
+    def check_for_unhandled_triggers(self, num_running: int) -> None:
+        """
+        Shut down if the subprocess trigger count disagrees with the 
supervisor.
+
+        Only valid between finished-removal and to_create-addition in 
``_handle_request``.
+        """
+        expected = len(self.running_triggers)
+        if expected != num_running:
+            log.error(

Review Comment:
   Uses the module-level `log`, but `_handle_request` already receives a bound 
`log: FilteringBoundLogger` that carries the request context. Passing that 
through would keep this message correlated with the rest of the request's 
logging.
   
   ---
   Drafted-by: Claude Code (Opus 5); reviewed by @potiuk before posting



##########
airflow-core/src/airflow/jobs/triggerer_job_runner.py:
##########
@@ -1399,11 +1417,14 @@ def process_trigger_events(self, finished_ids: 
list[int]) -> messages.TriggerSta
             trigger_id, exc = self.failed_triggers.popleft()
             tb = format_exception(type(exc), exc, exc.__traceback__) if exc 
else None
             failures_to_send.append((trigger_id, tb))
+            if trigger_id not in self.triggers:
+                finished_ids.append(trigger_id)

Review Comment:
   Mutating the caller's list in place. I traced it and it's harmless today — 
`finished_ids` is freshly built in `cleanup_finished_triggers()` and isn't read 
again after `sync_state_to_supervisor` returns — so this is style, not a bug.
   
   Still, `process_trigger_events` reads as a pure "build the message" 
function, and a caller that later reused its list would get a surprise. 
Building the combined list locally and leaving the parameter untouched keeps 
that property.
   
   ---
   Drafted-by: Claude Code (Opus 5); reviewed by @potiuk before posting



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