Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(fetch): Fix memory leak when handling endless streaming #13809

Merged
merged 5 commits into from
Oct 3, 2024

Conversation

soapproject
Copy link
Contributor

This is a quick fix to address a memory overflow issue caused by the recursive approach when handling endless streams (e.g., CCTV).

However, this is not a perfect solution, as this approach still does not trigger the onFinishedResolving callback for streams that never terminate.

Fixes GH-13806

Before submitting a pull request, please take a look at our
Contributing guidelines and verify:

  • If you've added code that should be tested, please add tests.
  • [] Ensure your code lints and the test suite passes (yarn lint) & (yarn test).

The lints didn't pass but they are unrelated to the changes in this commit?
image

This is a quick fix to address a memory overflow issue caused by the recursive approach when handling endless streams (e.g., CCTV).
However, this is not a perfect solution, as this approach still does not trigger the onFinishedResolving callback for streams that never terminate.

Fixes getsentryGH-13806
@mydea mydea requested a review from lforst September 26, 2024 11:03
adjust format
@AbhiPrasad AbhiPrasad self-requested a review September 26, 2024 12:59
@lforst lforst self-assigned this Sep 30, 2024
@lforst
Copy link
Member

lforst commented Sep 30, 2024

Hi, thanks for opening the PR! Would you mind outlining the thought process behind the releaseLock() call? I think I get it but want to be sure we all know what's going on because this is a super hot path in the SDK.

@soapproject
Copy link
Contributor Author

Hi, actually the improvement was referenced from GTP.
But I think it is correct to use releaseLock, after read the ReadableStream doc:
https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/getReader

getReader locks the stream and returns either a ReadableStreamDefaultReader or a ReadableStreamBYOBReader.
https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader/releaseLock
https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamBYOBReader/releaseLock

So we need to release the lock and de-activate the reader to ensure that res.body is not locked.

Maybe we can experiment with calling resolveResponse multiple times without releasing the lock to see what happens?

@soapproject
Copy link
Contributor Author

btw, we've encountered another issue when working with CCTV streaming. Even after leaving the page and calling videojs.dispose(), the stream continues to fetch data in the background.

I think this might require opening a new issue, but could this behavior be related to the code in fetch.ts?

@lforst
Copy link
Member

lforst commented Oct 2, 2024

I have updated this PR to:

  • not update the span duration in every case we cancel the operation
  • add a maximum timeout of 90s (this is arbitrary)
  • remove some unnecessary async/awaits
  • cancel the body (and implicitly the reader) to stop putting stuff into memory as it streams in

@lforst lforst requested a review from chargome October 2, 2024 14:30
@@ -158,7 +175,8 @@ async function streamHandler(response: Response): Promise<void> {
return;
}

await resolveResponse(clonedResponseForResolving, () => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
resolveResponse(clonedResponseForResolving, () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we want leave this floating?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is fine to have floating promises if you are certain that they cannot reject - i think this is the case here!

@lforst lforst merged commit 0b739c5 into getsentry:develop Oct 3, 2024
127 checks passed
alexandresoro pushed a commit to alexandresoro/ouca that referenced this pull request Oct 3, 2024
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@sentry/node](https://github.com/getsentry/sentry-javascript/tree/master/packages/node) ([source](https://github.com/getsentry/sentry-javascript)) | dependencies | minor | [`8.32.0` -> `8.33.1`](https://renovatebot.com/diffs/npm/@sentry%2fnode/8.32.0/8.33.1) |
| [@sentry/react](https://github.com/getsentry/sentry-javascript/tree/master/packages/react) ([source](https://github.com/getsentry/sentry-javascript)) | dependencies | minor | [`8.32.0` -> `8.33.1`](https://renovatebot.com/diffs/npm/@sentry%2freact/8.32.0/8.33.1) |

---

### Release Notes

<details>
<summary>getsentry/sentry-javascript (@&#8203;sentry/node)</summary>

### [`v8.33.1`](https://github.com/getsentry/sentry-javascript/releases/tag/8.33.1)

[Compare Source](getsentry/sentry-javascript@8.33.0...8.33.1)

-   fix(core): Update trpc middleware types ([#&#8203;13859](getsentry/sentry-javascript#13859))
-   fix(fetch): Fix memory leak when handling endless streaming
    ([#&#8203;13809](getsentry/sentry-javascript#13809))

Work in this release was contributed by [@&#8203;soapproject](https://github.com/soapproject). Thank you for your contribution!

##### Bundle size 📦

| Path                                                             | Size              |
| ---------------------------------------------------------------- | ----------------- |
| [@&#8203;sentry/browser](https://github.com/sentry/browser)                                                  | 22.64 KB  |
| [@&#8203;sentry/browser](https://github.com/sentry/browser) - with treeshaking flags                         | 21.42 KB  |
| [@&#8203;sentry/browser](https://github.com/sentry/browser) (incl. Tracing)                                  | 34.87 KB  |
| [@&#8203;sentry/browser](https://github.com/sentry/browser) (incl. Tracing, Replay)                          | 71.38 KB  |
| [@&#8203;sentry/browser](https://github.com/sentry/browser) (incl. Tracing, Replay) - with treeshaking flags | 61.81 KB  |
| [@&#8203;sentry/browser](https://github.com/sentry/browser) (incl. Tracing, Replay with Canvas)              | 75.73 KB  |
| [@&#8203;sentry/browser](https://github.com/sentry/browser) (incl. Tracing, Replay, Feedback)                | 88.5 KB   |
| [@&#8203;sentry/browser](https://github.com/sentry/browser) (incl. Tracing, Replay, Feedback, metrics)       | 90.38 KB  |
| [@&#8203;sentry/browser](https://github.com/sentry/browser) (incl. metrics)                                  | 26.91 KB  |
| [@&#8203;sentry/browser](https://github.com/sentry/browser) (incl. Feedback)                                 | 39.78 KB  |
| [@&#8203;sentry/browser](https://github.com/sentry/browser) (incl. sendFeedback)                             | 27.3 KB   |
| [@&#8203;sentry/browser](https://github.com/sentry/browser) (incl. FeedbackAsync)                            | 32.08 KB  |
| [@&#8203;sentry/react](https://github.com/sentry/react)                                                    | 25.39 KB  |
| [@&#8203;sentry/react](https://github.com/sentry/react) (incl. Tracing)                                    | 37.86 KB  |
| [@&#8203;sentry/vue](https://github.com/sentry/vue)                                                      | 26.8 KB   |
| [@&#8203;sentry/vue](https://github.com/sentry/vue) (incl. Tracing)                                      | 36.77 KB  |
| [@&#8203;sentry/svelte](https://github.com/sentry/svelte)                                                   | 22.77 KB  |
| CDN Bundle                                                       | 23.95 KB  |
| CDN Bundle (incl. Tracing)                                       | 36.66 KB  |
| CDN Bundle (incl. Tracing, Replay)                               | 71.15 KB  |
| CDN Bundle (incl. Tracing, Replay, Feedback)                     | 76.45 KB  |
| CDN Bundle - uncompressed                                        | 70.17 KB  |
| CDN Bundle (incl. Tracing) - uncompressed                        | 108.68 KB |
| CDN Bundle (incl. Tracing, Replay) - uncompressed                | 220.58 KB |
| CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed      | 233.79 KB |
| [@&#8203;sentry/nextjs](https://github.com/sentry/nextjs) (client)                                          | 37.82 KB  |
| [@&#8203;sentry/sveltekit](https://github.com/sentry/sveltekit) (client)                                       | 35.45 KB  |
| [@&#8203;sentry/node](https://github.com/sentry/node)                                                     | 125.13 KB |
| [@&#8203;sentry/node](https://github.com/sentry/node) - without tracing                                   | 93.58 KB  |
| [@&#8203;sentry/aws-serverless](https://github.com/sentry/aws-serverless)                                           | 103.28 KB |

### [`v8.33.0`](https://github.com/getsentry/sentry-javascript/blob/HEAD/CHANGELOG.md#8330)

[Compare Source](getsentry/sentry-javascript@8.32.0...8.33.0)

##### Important Changes

-   **feat(nextjs): Support new async APIs (`headers()`, `params`, `searchParams`)
    ([#&#8203;13828](getsentry/sentry-javascript#13828

Adds support for [new dynamic Next.js APIs](vercel/next.js#68812).

-   **feat(node): Add `lru-memoizer` instrumentation
    ([#&#8203;13796](getsentry/sentry-javascript#13796

Adds integration for lru-memoizer using [@&#8203;opentelemetry/instrumentation-lru-memoizer](https://github.com/opentelemetry/instrumentation-lru-memoizer).

-   **feat(nuxt): Add `unstable_sentryBundlerPluginOptions` to module options
    ([#&#8203;13811](getsentry/sentry-javascript#13811

Allows passing other options from the bundler plugins (vite and rollup) to Nuxt module options.

##### Other Changes

-   fix(browser): Ensure `wrap()` only returns functions
    ([#&#8203;13838](getsentry/sentry-javascript#13838))
-   fix(core): Adapt trpc middleware input attachment
    ([#&#8203;13831](getsentry/sentry-javascript#13831))
-   fix(core): Don't return trace data in `getTraceData` and `getTraceMetaTags` if SDK is disabled
    ([#&#8203;13760](getsentry/sentry-javascript#13760))
-   fix(nuxt): Don't restrict source map assets upload
    ([#&#8203;13800](getsentry/sentry-javascript#13800))
-   fix(nuxt): Use absolute path for client config ([#&#8203;13798](getsentry/sentry-javascript#13798))
-   fix(replay): Stop global event handling for paused replays
    ([#&#8203;13815](getsentry/sentry-javascript#13815))
-   fix(sveltekit): add url param to source map upload options
    ([#&#8203;13812](getsentry/sentry-javascript#13812))
-   fix(types): Add jsdocs to cron types ([#&#8203;13776](getsentry/sentry-javascript#13776))
-   fix(nextjs): Loosen [@&#8203;sentry/nextjs](https://github.com/sentry/nextjs) webpack peer dependency
    ([#&#8203;13826](getsentry/sentry-javascript#13826))

Work in this release was contributed by [@&#8203;joshuajaco](https://github.com/joshuajaco). Thank you for your contribution!

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMDYuNCIsInVwZGF0ZWRJblZlciI6IjM4LjEwNy4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->

Reviewed-on: https://git.tristess.app/alexandresoro/ouca/pulls/186
Reviewed-by: Alexandre Soro <code@soro.dev>
Co-authored-by: renovate <renovate@git.tristess.app>
Co-committed-by: renovate <renovate@git.tristess.app>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Memory leak with endless streaming (example: CCTV)
3 participants