68 lines
1.1 KiB
JavaScript
68 lines
1.1 KiB
JavaScript
'use strict';
|
|
|
|
const SQLITE_BUSY_RETRY_DELAYS_MS = [
|
|
25,
|
|
50,
|
|
100,
|
|
200,
|
|
400,
|
|
800,
|
|
1600,
|
|
];
|
|
|
|
function sleep(ms) {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
function isSqliteBusy(error) {
|
|
if (!error) return false;
|
|
|
|
if (
|
|
error.code === 'SQLITE_BUSY' ||
|
|
error.code === 'SQLITE_LOCKED'
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
const message = String(
|
|
error.message || error
|
|
).toLowerCase();
|
|
|
|
return (
|
|
message.includes('database is locked') ||
|
|
message.includes('database table is locked')
|
|
);
|
|
}
|
|
|
|
async function withSqliteBusyRetry(label, operation) {
|
|
let retry = 0;
|
|
|
|
while (true) {
|
|
try {
|
|
return await operation();
|
|
} catch (error) {
|
|
if (
|
|
!isSqliteBusy(error) ||
|
|
retry >= SQLITE_BUSY_RETRY_DELAYS_MS.length
|
|
) {
|
|
throw error;
|
|
}
|
|
|
|
const delay = SQLITE_BUSY_RETRY_DELAYS_MS[retry];
|
|
retry += 1;
|
|
|
|
console.warn(
|
|
`[SQLiteRetry] SQLITE_BUSY ${label}; ` +
|
|
`retry=${retry}/${SQLITE_BUSY_RETRY_DELAYS_MS.length} ` +
|
|
`delay=${delay}ms`
|
|
);
|
|
|
|
await sleep(delay);
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
isSqliteBusy,
|
|
withSqliteBusyRetry,
|
|
};
|