diff --git a/packages/node/src/anr/index.ts b/packages/node/src/anr/index.ts index 1d4d61b78b55..9c6827c38259 100644 --- a/packages/node/src/anr/index.ts +++ b/packages/node/src/anr/index.ts @@ -138,6 +138,20 @@ function startChildProcess(options: Options): void { } } +function createHrTimer(): { getTimeMs: () => number; reset: () => void } { + let lastPoll = process.hrtime(); + + return { + getTimeMs: (): number => { + const [seconds, nanoSeconds] = process.hrtime(lastPoll); + return Math.floor(seconds * 1e3 + nanoSeconds / 1e6); + }, + reset: (): void => { + lastPoll = process.hrtime(); + }, + }; +} + function handleChildProcess(options: Options): void { function log(message: string): void { logger.log(`[ANR child process] ${message}`); @@ -182,7 +196,7 @@ function handleChildProcess(options: Options): void { } } - const { poll } = watchdogTimer(options.pollInterval, options.anrThreshold, watchdogTimeout); + const { poll } = watchdogTimer(createHrTimer, options.pollInterval, options.anrThreshold, watchdogTimeout); process.on('message', () => { poll(); diff --git a/packages/utils/src/anr.ts b/packages/utils/src/anr.ts index b007c1355cb7..89990c3414f7 100644 --- a/packages/utils/src/anr.ts +++ b/packages/utils/src/anr.ts @@ -10,6 +10,8 @@ type WatchdogReturn = { enabled: (state: boolean) => void; }; +type CreateTimerImpl = () => { getTimeMs: () => number; reset: () => void }; + /** * A node.js watchdog timer * @param pollInterval The interval that we expect to get polled at @@ -17,14 +19,18 @@ type WatchdogReturn = { * @param callback The callback to call for ANR * @returns An object with `poll` and `enabled` functions {@link WatchdogReturn} */ -export function watchdogTimer(pollInterval: number, anrThreshold: number, callback: () => void): WatchdogReturn { - let lastPoll = process.hrtime(); +export function watchdogTimer( + createTimer: CreateTimerImpl, + pollInterval: number, + anrThreshold: number, + callback: () => void, +): WatchdogReturn { + const timer = createTimer(); let triggered = false; let enabled = true; setInterval(() => { - const [seconds, nanoSeconds] = process.hrtime(lastPoll); - const diffMs = Math.floor(seconds * 1e3 + nanoSeconds / 1e6); + const diffMs = timer.getTimeMs(); if (triggered === false && diffMs > pollInterval + anrThreshold) { triggered = true; @@ -40,7 +46,7 @@ export function watchdogTimer(pollInterval: number, anrThreshold: number, callba return { poll: () => { - lastPoll = process.hrtime(); + timer.reset(); }, enabled: (state: boolean) => { enabled = state;