Repository navigation
Conversation
|
|
Hi @ghazy2001, thanks for your interest in contributing! This project requires that pull request authors are vouched, and you are not in the list of vouched users. This PR will be closed automatically. See https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md for more details. |
|
Caution Review failedThe pull request is closed.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
| for (const signal of validSignals) { | ||
| signal.addEventListener("abort", onAbort, { once: true }); | ||
| } |
There was a problem hiding this comment.
🟡 Completed turns retain abort listeners
On runtimes without AbortSignal.any, anySignal retains listeners after a normal chat turn completes. Neither runSignal nor the per-turn stop signal aborts, so long-lived runs accumulate listeners and controllers.
Learn more
The fallback subscribes to each input signal and removes those listeners only when an input aborts. A managed chat turn creates a new stop controller and combines it with the run-wide signal in the turn setup. Normal completion does not abort either signal, so the run-wide signal keeps every prior turn's closure, controller, and stop signal alive. The custom session turn also replaces its stop controller without aborting the old one in reset. This differs from native AbortSignal.any, which does not keep an otherwise unreferenced composite alive through strong event listeners.
Example: On a runtime without AbortSignal.any, a chat agent finishes 80 normal turns. Its run-wide signal still holds 80 listeners referencing obsolete stop controllers until the run ends.
Recommended fix: Provide a way to dispose the fallback's source listeners when the composite's operation ends, and invoke it at each turn and subscription teardown. Preserve the existing abort propagation and reason while an operation remains active.
Was this helpful? React with 👍 or 👎 to provide feedback.
| * with listeners on environments where `AbortSignal.any` is not supported (such as | ||
| * Safari < 17.4 or Node < 20.3). | ||
| */ | ||
| export function anySignal(signals: (AbortSignal | undefined | null)[]): AbortSignal { |
There was a problem hiding this comment.
🟡 Safari fix lacks a release changeset
The anySignal fallback fixes a user-visible SDK failure, but this PR includes no changeset. The SDK release loses its required patch note.
Learn more
The SDK is a public package, and the new fallback lets customers use chat transports on older Safari versions that previously threw. Repository guidance requires a changeset when a public package fixes a bug users could hit. No changeset is added in this PR.
Example: A customer deciding whether to upgrade for Safari support reads the SDK changelog and finds no entry for the fix.
Recommended fix: Add a patch changeset for @trigger.dev/sdk, phrased in terms of older Safari chat transport compatibility.
Was this helpful? React with 👍 or 👎 to provide feedback.
| const c1 = new AbortController(); | ||
| const c2 = new AbortController(); | ||
|
|
||
| const c2RemoveSpy = vi.spyOn(c2.signal, "removeEventListener"); |
There was a problem hiding this comment.
🟡 Fallback test uses a forbidden spy
The listener-cleanup test calls vi.spyOn, despite the repository's explicit ban on spies in tests. Its assertion also couples the test to listener-removal internals.
Learn more
Example: A fallback implementation that manages listeners through another valid mechanism can fail the test solely because it never calls the spied-on method.
Recommended fix: Replace the spy with an observable behavioral test that covers the listener-lifetime regression without intercepting removeEventListener.
Was this helpful? React with 👍 or 👎 to provide feedback.
| describe("anySignal", () => { | ||
| it("returns a non-aborted signal when signals list is empty", () => { |
| expect(stream).toBeDefined(); | ||
| abort.abort(); |
Overview
Fixes #5098
On Safari < 17.4 (and Node < 20.3), \AbortSignal.any\ is undefined, causing chat transports (\useTriggerChatTransport, \subscribeToSessionStream,
econnectToStream) to throw:
\
TypeError: AbortSignal.any is not a function. (In 'AbortSignal.any([t,o.signal])', 'AbortSignal.any' is undefined)
\\
Changes
econnectToStream\ and \subscribeToSessionStream)
econnectToStream\ safely handles aborted signals when \AbortSignal.any\ is deleted.
Verification