Skip to content

Commit 1ffba2c

Browse files
authored
fix(core): Do not remove promiseBuffer entirely (#19592)
closes #19589 closes [JS-1839](https://linear.app/getsentry/issue/JS-1839/flushanddispose-in-10410-crashes-when-workerentrypoint-rpc-methods-use) It seems that there are way to rely on the memory leak on Cloudflare. When that is the case the promise buffer is set to undefined and would fail in a latter step. Creating a new promise buffer would release everything we had before and mark with that it would be ready to be released by the garbage collector. The transport above is ok to be set to undefined, as it is readonly on TypeScript level.
1 parent 4a7c056 commit 1ffba2c

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

packages/core/src/server-runtime-client.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { getIsolationScope } from './currentScopes';
44
import { DEBUG_BUILD } from './debug-build';
55
import type { Scope } from './scope';
66
import { registerSpanErrorInstrumentation } from './tracing';
7+
import { DEFAULT_TRANSPORT_BUFFER_SIZE } from './transports/base';
78
import { addUserAgentToTransportHeaders } from './transports/userAgent';
89
import type { CheckIn, MonitorConfig, SerializedCheckIn } from './types-hoist/checkin';
910
import type { Event, EventHint } from './types-hoist/event';
@@ -14,7 +15,7 @@ import type { BaseTransportOptions, Transport } from './types-hoist/transport';
1415
import { debug } from './utils/debug-logger';
1516
import { eventFromMessage, eventFromUnknownInput } from './utils/eventbuilder';
1617
import { uuid4 } from './utils/misc';
17-
import type { PromiseBuffer } from './utils/promisebuffer';
18+
import { makePromiseBuffer } from './utils/promisebuffer';
1819
import { resolvedSyncPromise } from './utils/syncpromise';
1920
import { _getTraceInfoFromScope } from './utils/trace-info';
2021

@@ -176,7 +177,7 @@ export class ServerRuntimeClient<
176177
this._integrations = {};
177178
this._outcomes = {};
178179
(this as unknown as { _transport?: Transport })._transport = undefined;
179-
(this as unknown as { _promiseBuffer?: PromiseBuffer<unknown> })._promiseBuffer = undefined;
180+
this._promiseBuffer = makePromiseBuffer(DEFAULT_TRANSPORT_BUFFER_SIZE);
180181
}
181182

182183
/**

packages/core/test/lib/server-runtime-client.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,4 +301,24 @@ describe('ServerRuntimeClient', () => {
301301
);
302302
});
303303
});
304+
305+
describe('dispose', () => {
306+
it('resets _promiseBuffer to a new empty buffer instead of undefined', () => {
307+
const options = getDefaultClientOptions({ dsn: PUBLIC_DSN });
308+
client = new ServerRuntimeClient(options);
309+
310+
// Access the private _promiseBuffer before dispose
311+
const originalBuffer = client['_promiseBuffer'];
312+
expect(originalBuffer).toBeDefined();
313+
314+
client.dispose();
315+
316+
// After dispose, _promiseBuffer should still be defined (not undefined)
317+
const bufferAfterDispose = client['_promiseBuffer'];
318+
expect(bufferAfterDispose).toBeDefined();
319+
expect(bufferAfterDispose).not.toBe(originalBuffer);
320+
// Verify it's a fresh buffer with no pending items
321+
expect(bufferAfterDispose.$).toEqual([]);
322+
});
323+
});
304324
});

0 commit comments

Comments
 (0)