Skip to content

feat(core): clear up integrations on dispose#20407

Open
JPeer264 wants to merge 2 commits intodevelopfrom
jp/cloudflare-oom
Open

feat(core): clear up integrations on dispose#20407
JPeer264 wants to merge 2 commits intodevelopfrom
jp/cloudflare-oom

Conversation

@JPeer264
Copy link
Copy Markdown
Member

@JPeer264 JPeer264 commented Apr 20, 2026

closes #19573
closes JS-1829

As with Cloudflare we create a new client on every request, that means that every integration that uses an addHandler and is used by the Cloudflare SDK is makes the client not disposable - so the garbage collector can't remove it properly.

This PR adds a callback for addHandler that basically removes the handler from the global handler array (for now only for integrations, which are used by the Cloudflare SDK). I actually also tried to change the global handler to be a WeakMap, but it still showed some memory leaks with that, so we need to actively remove these callbacks.

For now, to not increase the bundle sizes for core too much, it is actually removing the handlers only in the ServerRuntimeClient, as for browsers it is usually not really an issue.

@linear-code
Copy link
Copy Markdown

linear-code bot commented Apr 20, 2026

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 20, 2026

size-limit report 📦

Path Size % Change Change
@sentry/browser 25.92 kB +0.18% +46 B 🔺
@sentry/browser - with treeshaking flags 24.4 kB +0.21% +49 B 🔺
@sentry/browser (incl. Tracing) 43.87 kB +0.15% +62 B 🔺
@sentry/browser (incl. Tracing + Span Streaming) 45.58 kB +0.18% +78 B 🔺
@sentry/browser (incl. Tracing, Profiling) 48.8 kB +0.14% +67 B 🔺
@sentry/browser (incl. Tracing, Replay) 83.05 kB +0.09% +71 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 72.56 kB +0.09% +60 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 87.74 kB +0.08% +67 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 99.99 kB +0.07% +64 B 🔺
@sentry/browser (incl. Feedback) 42.76 kB +0.14% +57 B 🔺
@sentry/browser (incl. sendFeedback) 30.6 kB +0.17% +51 B 🔺
@sentry/browser (incl. FeedbackAsync) 35.61 kB +0.17% +57 B 🔺
@sentry/browser (incl. Metrics) 27.22 kB +0.22% +58 B 🔺
@sentry/browser (incl. Logs) 27.34 kB +0.19% +51 B 🔺
@sentry/browser (incl. Metrics & Logs) 28.04 kB +0.22% +60 B 🔺
@sentry/react 27.68 kB +0.2% +54 B 🔺
@sentry/react (incl. Tracing) 46.1 kB +0.12% +55 B 🔺
@sentry/vue 30.76 kB +0.16% +49 B 🔺
@sentry/vue (incl. Tracing) 45.68 kB +0.14% +61 B 🔺
@sentry/svelte 25.95 kB +0.2% +51 B 🔺
CDN Bundle 28.63 kB +0.3% +85 B 🔺
CDN Bundle (incl. Tracing) 45.01 kB +0.16% +69 B 🔺
CDN Bundle (incl. Logs, Metrics) 30 kB +0.26% +77 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) 46.1 kB +0.17% +77 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) 68.98 kB +0.12% +82 B 🔺
CDN Bundle (incl. Tracing, Replay) 82.03 kB +0.09% +73 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 83.12 kB +0.11% +91 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 87.53 kB +0.09% +71 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 88.63 kB +0.1% +82 B 🔺
CDN Bundle - uncompressed 83.56 kB +0.2% +162 B 🔺
CDN Bundle (incl. Tracing) - uncompressed 134.47 kB +0.13% +162 B 🔺
CDN Bundle (incl. Logs, Metrics) - uncompressed 87.76 kB +0.25% +212 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 137.93 kB +0.16% +212 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 211.33 kB +0.11% +212 B 🔺
CDN Bundle (incl. Tracing, Replay) - uncompressed 251.91 kB +0.07% +162 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 255.35 kB +0.09% +212 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 264.82 kB +0.07% +162 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 268.26 kB +0.08% +212 B 🔺
@sentry/nextjs (client) 48.64 kB +0.13% +63 B 🔺
@sentry/sveltekit (client) 44.29 kB +0.16% +70 B 🔺
@sentry/node-core 58.11 kB +0.17% +95 B 🔺
@sentry/node 174.98 kB +0.06% +95 B 🔺
@sentry/node - without tracing 98.07 kB +0.11% +104 B 🔺
@sentry/aws-serverless 115.29 kB +0.09% +98 B 🔺

View base workflow run

@JPeer264 JPeer264 self-assigned this Apr 21, 2026
@JPeer264 JPeer264 requested review from mydea and s1gr1d April 21, 2026 07:52
@JPeer264 JPeer264 marked this pull request as ready for review April 21, 2026 08:17
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a589811. Configure here.

typeHandlers.splice(index, 1);
}
}
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Array splice during for...of iteration may skip handlers

Low Severity

The new unsubscribe function uses splice to remove handlers from the live handlers[type] array. If an unsubscribe is ever called while triggerHandlers is iterating over the same array with for...of, the in-place mutation can cause the iterator to skip the next handler. JavaScript's ArrayIterator tracks position by index — when splice removes an element at or before the current position, subsequent elements shift down and the next one is silently skipped. While unlikely in current usage (unsubscribe is called from dispose(), not during handler execution), this creates a latent hazard if future code paths ever trigger disposal from within a handler callback.

Additional Locations (1)
Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bot

Reviewed by Cursor Bugbot for commit a589811. Configure here.

cleanups.forEach(cleanup => {
expect(cleanup).toHaveBeenCalledTimes(1);
});
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No integration or E2E test for feature

Low Severity

This feat PR only includes unit tests. There is no integration or E2E test verifying the end-to-end behavior — e.g., that setting up consoleIntegration on a ServerRuntimeClient, then calling dispose(), actually removes the handler from the global handlers array. An integration test exercising this full flow (especially in a Cloudflare-like scenario with multiple client lifecycles) would help catch regressions in the memory-leak fix.

Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bot

Reviewed by Cursor Bugbot for commit a589811. Configure here.

@JPeer264 JPeer264 requested a review from chargome April 21, 2026 09:01
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.

Investigate in memory leak within console integrations on Cloudflare

1 participant