test(electron): cover renderer recovery policy
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
const RECOVERY_WINDOW_MS = 60_000;
|
||||||
|
const MAX_RECOVERY_ATTEMPTS = 3;
|
||||||
|
|
||||||
|
const RECOVERABLE_REASONS = new Set([
|
||||||
|
'abnormal-exit',
|
||||||
|
'crashed',
|
||||||
|
'oom',
|
||||||
|
'memory-eviction',
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const createRendererRecoveryPolicy = (now = Date.now) => {
|
||||||
|
let windowStartedAt = 0;
|
||||||
|
let attempts = 0;
|
||||||
|
|
||||||
|
return {
|
||||||
|
shouldReload: (reason) => {
|
||||||
|
if (!RECOVERABLE_REASONS.has(reason)) return false;
|
||||||
|
|
||||||
|
const currentTime = now();
|
||||||
|
if (currentTime - windowStartedAt >= RECOVERY_WINDOW_MS) {
|
||||||
|
windowStartedAt = currentTime;
|
||||||
|
attempts = 0;
|
||||||
|
}
|
||||||
|
if (attempts >= MAX_RECOVERY_ATTEMPTS) return false;
|
||||||
|
|
||||||
|
attempts += 1;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import test from 'node:test';
|
||||||
|
|
||||||
|
import { createRendererRecoveryPolicy } from './renderer-recovery.mjs';
|
||||||
|
|
||||||
|
test('allows a bounded number of reloads for recoverable renderer failures', () => {
|
||||||
|
const policy = createRendererRecoveryPolicy(() => 1_000);
|
||||||
|
|
||||||
|
assert.equal(policy.shouldReload('crashed'), true);
|
||||||
|
assert.equal(policy.shouldReload('oom'), true);
|
||||||
|
assert.equal(policy.shouldReload('abnormal-exit'), true);
|
||||||
|
assert.equal(policy.shouldReload('memory-eviction'), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('ignores clean and externally killed renderer exits', () => {
|
||||||
|
const policy = createRendererRecoveryPolicy(() => 1_000);
|
||||||
|
|
||||||
|
assert.equal(policy.shouldReload('clean-exit'), false);
|
||||||
|
assert.equal(policy.shouldReload('killed'), false);
|
||||||
|
assert.equal(policy.shouldReload('launch-failed'), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('resets the recovery budget after the recovery window', () => {
|
||||||
|
let currentTime = 1_000;
|
||||||
|
const policy = createRendererRecoveryPolicy(() => currentTime);
|
||||||
|
|
||||||
|
assert.equal(policy.shouldReload('crashed'), true);
|
||||||
|
assert.equal(policy.shouldReload('crashed'), true);
|
||||||
|
assert.equal(policy.shouldReload('crashed'), true);
|
||||||
|
assert.equal(policy.shouldReload('crashed'), false);
|
||||||
|
|
||||||
|
currentTime += 60_000;
|
||||||
|
assert.equal(policy.shouldReload('crashed'), true);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user