Skip to content

Commit 43b83a6

Browse files
authored
fix(core): [v7] unref timer to not block node exit (#11483)
This backports #11430 to v7
1 parent 9bfadb5 commit 43b83a6

File tree

6 files changed

+77
-7
lines changed

6 files changed

+77
-7
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const Sentry = require('@sentry/node');
2+
3+
function configureSentry() {
4+
Sentry.init({
5+
dsn: 'https://[email protected]/1337',
6+
release: '1.0',
7+
autoSessionTracking: false,
8+
});
9+
10+
Sentry.metrics.increment('test');
11+
}
12+
13+
async function main() {
14+
configureSentry();
15+
await new Promise(resolve => setTimeout(resolve, 1000));
16+
process.exit(0);
17+
}
18+
19+
main();
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const Sentry = require('@sentry/node');
2+
3+
function configureSentry() {
4+
Sentry.init({
5+
dsn: 'https://[email protected]/1337',
6+
release: '1.0',
7+
autoSessionTracking: false,
8+
});
9+
10+
Sentry.metrics.increment('test');
11+
}
12+
13+
async function main() {
14+
configureSentry();
15+
await new Promise(resolve => setTimeout(resolve, 1000));
16+
}
17+
18+
main();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createRunner } from '../../utils/runner';
2+
3+
describe('metrics', () => {
4+
test('should exit', done => {
5+
const runner = createRunner(__dirname, 'should-exit.js').start();
6+
7+
setTimeout(() => {
8+
expect(runner.childHasExited()).toBe(true);
9+
done();
10+
}, 5_000);
11+
});
12+
13+
test('should exit forced', done => {
14+
const runner = createRunner(__dirname, 'should-exit-forced.js').start();
15+
16+
setTimeout(() => {
17+
expect(runner.childHasExited()).toBe(true);
18+
done();
19+
}, 5_000);
20+
});
21+
});

dev-packages/node-integration-tests/suites/tracing/metric-summaries/scenario.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ Sentry.init({
1111
},
1212
});
1313

14-
// Stop the process from exiting before the transaction is sent
15-
setInterval(() => {}, 1000);
16-
1714
Sentry.startSpan(
1815
{
1916
name: 'Test Transaction',

packages/core/src/metrics/aggregator.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ export class MetricsAggregator implements MetricsAggregatorBase {
2525
// that we store in memory.
2626
private _bucketsTotalWeight;
2727

28-
private readonly _interval: ReturnType<typeof setInterval>;
28+
// Cast to any so that it can use Node.js timeout
29+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
30+
private readonly _interval: any;
2931

3032
// SDKs are required to shift the flush interval by random() * rollup_in_seconds.
3133
// That shift is determined once per startup to create jittering.
@@ -42,7 +44,13 @@ export class MetricsAggregator implements MetricsAggregatorBase {
4244
public constructor(private readonly _client: Client<ClientOptions>) {
4345
this._buckets = new Map();
4446
this._bucketsTotalWeight = 0;
45-
this._interval = setInterval(() => this._flush(), DEFAULT_FLUSH_INTERVAL);
47+
48+
this._interval = setInterval(() => this._flush(), DEFAULT_FLUSH_INTERVAL) as any;
49+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
50+
if (this._interval.unref) {
51+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
52+
this._interval.unref();
53+
}
4654
this._flushShift = Math.floor((Math.random() * DEFAULT_FLUSH_INTERVAL) / 1000);
4755
this._forceFlush = false;
4856
}

packages/core/src/sessionflusher.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ export class SessionFlusher implements SessionFlusherLike {
2020
public readonly flushTimeout: number;
2121
private _pendingAggregates: Record<number, AggregationCounts>;
2222
private _sessionAttrs: ReleaseHealthAttributes;
23-
private _intervalId: ReturnType<typeof setInterval>;
23+
// Cast to any so that it can use Node.js timeout
24+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
25+
private _intervalId: any;
2426
private _isEnabled: boolean;
2527
private _client: Client;
2628

@@ -30,8 +32,13 @@ export class SessionFlusher implements SessionFlusherLike {
3032
this._pendingAggregates = {};
3133
this._isEnabled = true;
3234

33-
// Call to setInterval, so that flush is called every 60 seconds
35+
// Call to setInterval, so that flush is called every 60 seconds.
3436
this._intervalId = setInterval(() => this.flush(), this.flushTimeout * 1000);
37+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
38+
if (this._intervalId.unref) {
39+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
40+
this._intervalId.unref();
41+
}
3542
this._sessionAttrs = attrs;
3643
}
3744

0 commit comments

Comments
 (0)