Better locking in local cache
Fixes occassional lock expired errors after updating presets, etc.
This commit is contained in:
1 parent
eb5caa6b5a
commit
5806fe2df6
3 files changed
+28
-31
No files matched your search
+5
-15
@@ -86,21 +86,11 @@ export async function acquireLock(
|
|||||||
if (Math.abs(v["timestamp"].getTime() - now) > CLOCK_SKEW_TOLERANCE)
|
if (Math.abs(v["timestamp"].getTime() - now) > CLOCK_SKEW_TOLERANCE)
|
||||||
throw new Error("Database clock skew too great");
|
throw new Error("Database clock skew too great");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.code === 11000) {
|
if (err.code !== 11000) throw err;
|
||||||
if (timeout > 0) {
|
if (!(timeout > 0)) return null;
|
||||||
return new Promise((resolve, reject) => {
|
const w = 50 + Math.random() * 50;
|
||||||
const w = 50 + Math.random() * 50;
|
await new Promise((resolve) => setTimeout(resolve, w));
|
||||||
setTimeout(() => {
|
return acquireLock(lockName, ttl, timeout - w, token);
|
||||||
acquireLock(lockName, ttl, timeout - w, token).then(
|
|
||||||
resolve,
|
|
||||||
reject
|
|
||||||
);
|
|
||||||
}, w);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
throw new Error("Failed to acquire lock");
|
|
||||||
}
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
|
|||||||
+11
-10
@@ -213,12 +213,13 @@ async function writeResponse(
|
|||||||
currentSessions.set(connection, sessionContext);
|
currentSessions.set(connection, sessionContext);
|
||||||
if (now >= sessionContext.extendLock) {
|
if (now >= sessionContext.extendLock) {
|
||||||
sessionContext.extendLock = now + 10000;
|
sessionContext.extendLock = now + 10000;
|
||||||
await cache.acquireLock(
|
const lockToken = await cache.acquireLock(
|
||||||
`cwmp_session_${sessionContext.deviceId}`,
|
`cwmp_session_${sessionContext.deviceId}`,
|
||||||
sessionContext.timeout * 1000 + 15000,
|
sessionContext.timeout * 1000 + 15000,
|
||||||
0,
|
0,
|
||||||
sessionContext.sessionId
|
sessionContext.sessionId
|
||||||
);
|
);
|
||||||
|
if (!lockToken) throw new Error("Failed to extend lock");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1149,15 +1150,15 @@ async function processRequest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
sessionContext.extendLock = sessionContext.timestamp + 10000;
|
||||||
sessionContext.extendLock = sessionContext.timestamp + 10000;
|
const lockToken = await cache.acquireLock(
|
||||||
await cache.acquireLock(
|
`cwmp_session_${sessionContext.deviceId}`,
|
||||||
`cwmp_session_${sessionContext.deviceId}`,
|
sessionContext.timeout * 1000 + 15000,
|
||||||
sessionContext.timeout * 1000 + 15000,
|
0,
|
||||||
0,
|
sessionContext.sessionId
|
||||||
sessionContext.sessionId
|
);
|
||||||
);
|
|
||||||
} catch (err) {
|
if (!lockToken) {
|
||||||
logger.accessError({
|
logger.accessError({
|
||||||
message: "CPE already in session",
|
message: "CPE already in session",
|
||||||
sessionContext: sessionContext,
|
sessionContext: sessionContext,
|
||||||
|
|||||||
+12
-6
@@ -380,13 +380,15 @@ async function fetchConfig(): Promise<[Config, UiConfig]> {
|
|||||||
async function refresh(): Promise<void> {
|
async function refresh(): Promise<void> {
|
||||||
if (!nextRefresh) {
|
if (!nextRefresh) {
|
||||||
await new Promise((resolve) => setTimeout(resolve, 20));
|
await new Promise((resolve) => setTimeout(resolve, 20));
|
||||||
await refresh();
|
return refresh();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nextRefresh = 0;
|
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
||||||
|
if (now < nextRefresh) return;
|
||||||
|
|
||||||
|
nextRefresh = 0;
|
||||||
|
|
||||||
const dbHash = await cache.get("presets_hash");
|
const dbHash = await cache.get("presets_hash");
|
||||||
|
|
||||||
if (currentSnapshot && dbHash === currentSnapshot) {
|
if (currentSnapshot && dbHash === currentSnapshot) {
|
||||||
@@ -394,7 +396,7 @@ async function refresh(): Promise<void> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const lockToken = await cache.acquireLock("presets_hash_lock", 5000, 5000);
|
const lockToken = await cache.acquireLock("presets_hash_lock", 5000);
|
||||||
|
|
||||||
const res = await Promise.all([
|
const res = await Promise.all([
|
||||||
fetchPresets(),
|
fetchPresets(),
|
||||||
@@ -427,8 +429,12 @@ async function refresh(): Promise<void> {
|
|||||||
|
|
||||||
currentSnapshot = computeHash(snapshot);
|
currentSnapshot = computeHash(snapshot);
|
||||||
snapshots.set(currentSnapshot, snapshot);
|
snapshots.set(currentSnapshot, snapshot);
|
||||||
await cache.set("presets_hash", currentSnapshot, 300);
|
|
||||||
await cache.releaseLock("presets_hash_lock", lockToken);
|
if (lockToken) {
|
||||||
|
if (currentSnapshot !== dbHash)
|
||||||
|
await cache.set("presets_hash", currentSnapshot, 300);
|
||||||
|
await cache.releaseLock("presets_hash_lock", lockToken);
|
||||||
|
}
|
||||||
|
|
||||||
nextRefresh = now + (REFRESH - (now % REFRESH));
|
nextRefresh = now + (REFRESH - (now % REFRESH));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user