fix(desktop): retry Windows settings file replacement
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import { replaceFileWithRetry } from './windows-file-replace.mjs';
|
||||
|
||||
const fileError = (code = 'EPERM') => Object.assign(new Error(code), { code });
|
||||
|
||||
test('retries transient Windows rename failures until replacement succeeds', async () => {
|
||||
const delays = [];
|
||||
let attempts = 0;
|
||||
|
||||
await replaceFileWithRetry('settings.tmp', 'settings.json', {
|
||||
platform: 'win32',
|
||||
rename: async () => {
|
||||
attempts += 1;
|
||||
if (attempts < 4) throw fileError();
|
||||
},
|
||||
wait: async (delay) => delays.push(delay),
|
||||
});
|
||||
|
||||
assert.equal(attempts, 4);
|
||||
assert.deepEqual(delays, [50, 100, 200]);
|
||||
});
|
||||
|
||||
test('does not retry rename errors that are not transient Windows locks', async () => {
|
||||
let attempts = 0;
|
||||
const error = fileError('ENOENT');
|
||||
|
||||
await assert.rejects(
|
||||
replaceFileWithRetry('settings.tmp', 'settings.json', {
|
||||
platform: 'win32',
|
||||
rename: async () => {
|
||||
attempts += 1;
|
||||
throw error;
|
||||
},
|
||||
wait: async () => assert.fail('unexpected wait'),
|
||||
}),
|
||||
error,
|
||||
);
|
||||
|
||||
assert.equal(attempts, 1);
|
||||
});
|
||||
|
||||
test('does not retry transient error codes outside Windows', async () => {
|
||||
let attempts = 0;
|
||||
const error = fileError();
|
||||
|
||||
await assert.rejects(
|
||||
replaceFileWithRetry('settings.tmp', 'settings.json', {
|
||||
platform: 'linux',
|
||||
rename: async () => {
|
||||
attempts += 1;
|
||||
throw error;
|
||||
},
|
||||
wait: async () => assert.fail('unexpected wait'),
|
||||
}),
|
||||
error,
|
||||
);
|
||||
|
||||
assert.equal(attempts, 1);
|
||||
});
|
||||
|
||||
test('returns the final Windows lock error after the retry window', async () => {
|
||||
const delays = [];
|
||||
let attempts = 0;
|
||||
|
||||
await assert.rejects(
|
||||
replaceFileWithRetry('settings.tmp', 'settings.json', {
|
||||
platform: 'win32',
|
||||
rename: async () => {
|
||||
attempts += 1;
|
||||
throw fileError();
|
||||
},
|
||||
wait: async (delay) => delays.push(delay),
|
||||
}),
|
||||
{ code: 'EPERM' },
|
||||
);
|
||||
|
||||
assert.equal(attempts, 8);
|
||||
assert.deepEqual(delays, [50, 100, 200, 400, 800, 1_000, 1_000]);
|
||||
});
|
||||
Reference in New Issue
Block a user