Conversation
d-hervas
force-pushed
the
fix/cloudwatch-trigger-stream-lifecycle
branch
from
September 11, 2026 22:40
03181be to
348ef21
Compare
subhramit
reviewed
Sep 12, 2026
d-hervas
force-pushed
the
fix/cloudwatch-trigger-stream-lifecycle
branch
9 times, most recently
from
September 20, 2026 16:33
05734b9 to
c506083
Compare
o-nikolas
reviewed
Sep 24, 2026
o-nikolas
reviewed
Sep 24, 2026
o-nikolas
left a comment
Contributor
There was a problem hiding this comment.
I think this needs a few pairs of eyes, logging is critical code. Left one comment
Co-authored-by: Niko Oliveira <onikolas@amazon.com>
d-hervas
force-pushed
the
fix/cloudwatch-trigger-stream-lifecycle
branch
from
September 25, 2026 14:39
07517ee to
b8f87ba
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Structured Triggerer logging reused one queued Watchtower handler across all CloudWatch stream paths. Watchtower retains queue, sequence-token, and worker state for every path until that handler closes, while Airflow keeps the remote I/O object alive for the Triggerer process.
This change owns one Watchtower handler per active structured-log path and closes/removes that handler when
upload(path)signals completion. Other active paths remain live, a later reuse of the same path creates a fresh handler, and records racing with close cannot reopen the path during teardown. The legacy task-handler path keeps its current behavior.Expected behavior
When
upload(path)marks one trigger stream complete, allqueued records for that stream are delivered and its Watchtower queue, worker,
and sequence-token state are released. Other active streams must remain usable,
and later reuse of the same path must create fresh state.
Failure mode
A long-lived Triggerer can process many distinct trigger log paths, including sequentially. With Watchtower's default queued delivery, the first record for each path creates a queue, sequence-token entry, and worker thread. Airflow calls
upload(path)when the trigger finishes, but the current implementation only flushes the shared handler.flush()delivers pending records without stopping the worker or removing that stream's state. Since the shared handler remains reachable for the lifetime of the Triggerer, retained state grows with the number of completed streams. Eventually the Triggerer's RSS or thread count can reach its container limit and the process is terminated withSIGKILL/OOM.The retention can be reproduced without AWS credentials or API calls using Watchtower 3.4.0. This mirrors the current provider behavior of changing
log_stream_nameon one queued handler:Output:
Calling
flush()therefore does not bound retained state as streams complete.Calling
close()stops all workers, but the current shared-handler design cannot do that for one completed stream without also closing other active streams.This change gives each active path an independently closable handler.
Related work
#70635 adds read-side discovery of deferred-task trigger log streams so they remain visible after deferral. This PR addresses the separate write-side lifecycle of those streams and releases Watchtower's retained queues, sequence-token state, and worker threads when each stream completes.
Validation
All 39 CloudWatch task-handler tests pass on Python 3.10.21 and Python 3.14.7. New tests cover active-stream isolation, repeated completion, exact-path reuse, 100 sequential processor-driven paths with no retained handlers, construction and close/log races, and final shutdown. Ruff, the Airflow Python 3.10 CI image's pinned mypy for both changed files, the full pre-commit
prekstage, andgit diff --checkalso pass.Was generative AI tooling used to co-author this PR?