Added cache invalidation functionality (#7279)
Josiah Baldwin committed
Feb 1, 2026 at 02:02 UTC
bfa8582fac9cb9283cb509517a77c1611ca93232
2 files changed
+46
-7
meshuser.js
+2
-1
@@ -5806,6 +5806,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
5806
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come.
5807
parent.parent.DispatchEvent(targets, obj, event);
5808
}
5809
+ parent.InvalidateNodeCache(newuser, node.meshid, node._id)
5810
}
5811
}
5812
@@ -5824,7 +5825,6 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
5825
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
5826
parent.parent.DispatchEvent(dispatchTargets, obj, event);
5827
}
5827
-
5828
if (command.responseid != null) { obj.send({ action: 'adddeviceuser', responseid: command.responseid, result: 'ok' }); }
5829
});
5830
}
@@ -5944,6 +5944,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
5944
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(mesh, [user._id, newuserid]), obj, event);
5945
if (command.remove === true) { msgs.push("Removed user " + newuserid.split('/')[2]); } else { msgs.push("Added user " + newuserid.split('/')[2]); }
5946
successCount++;
5947
+ parent.InvalidateNodeCache(newuser, mesh)
5948
} else {
5949
msgs.push("Unknown user " + newuserid.split('/')[2]);
5950
unknownUsers.push(newuserid.split('/')[2]);
webserver.js
+44
-6
@@ -9267,15 +9267,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
9267
if (typeof mesh == 'string') { meshid = mesh; } else if ((typeof mesh == 'object') && (typeof mesh._id == 'string')) { meshid = mesh._id; } else return 0;
9268
9269
// Check if we have this in the cache
9270
- const cacheid = user._id + '/' + meshid + '/' + nodeid;
9271
- const cache = GetNodeRightsCache[cacheid];
9270
+
9271
+ const cache = ((GetNodeRightsCache[user._id] || {})[meshid] || {})[nodeid];
9272
if (cache != null) { if (cache.t > Date.now()) { return cache.o; } else { GetNodeRightsCacheCount--; } } // Cache hit, or we need to update the cache
9273
- if (GetNodeRightsCacheCount > 2000) { GetNodeRightsCache = {}; GetNodeRightsCacheCount = 0; } // From time to time, flush the cache
9273
+ if (GetNodeRightsCacheCount > 2000) { obj.FlushGetNodeRightsCache() } // From time to time, flush the cache
9274
9275
var r = obj.GetMeshRights(user, mesh);
9276
if (r == 0xFFFFFFFF) {
9277
const out = removeUserRights(r, user);
9278
- GetNodeRightsCache[cacheid] = { t: Date.now() + 10000, o: out };
9278
+ GetNodeRightsCache[user._id] = GetNodeRightsCache[user._id] || {}
9279
+ GetNodeRightsCache[user._id][meshid] = GetNodeRightsCache[user._id][meshid] || {}
9280
+ GetNodeRightsCache[user._id][meshid][nodeid] = { t: Date.now() + 10000, o: out };
9281
GetNodeRightsCacheCount++;
9282
return out;
9283
}
@@ -9284,7 +9286,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
9286
if ((user.links != null) && (user.links[nodeid] != null)) { r |= user.links[nodeid].rights; } // TODO: Deal with reverse permissions
9287
if (r == 0xFFFFFFFF) {
9288
const out = removeUserRights(r, user);
9287
- GetNodeRightsCache[cacheid] = { t: Date.now() + 10000, o: out };
9289
+ GetNodeRightsCache[user._id] = GetNodeRightsCache[user._id] || {}
9290
+ GetNodeRightsCache[user._id][meshid] = GetNodeRightsCache[user._id][meshid] || {}
9291
+ GetNodeRightsCache[user._id][meshid][nodeid] = { t: Date.now() + 10000, o: out };
9292
GetNodeRightsCacheCount++;
9293
return out;
9294
}
@@ -9298,11 +9302,45 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
9302
}
9303
9304
const out = removeUserRights(r, user);
9301
- GetNodeRightsCache[cacheid] = { t: Date.now() + 10000, o: out };
9305
+ GetNodeRightsCache[user._id] = GetNodeRightsCache[user._id] || {}
9306
+ GetNodeRightsCache[user._id][meshid] = GetNodeRightsCache[user._id][meshid] || {}
9307
+ GetNodeRightsCache[user._id][meshid][nodeid] = { t: Date.now() + 10000, o: out };
9308
GetNodeRightsCacheCount++;
9309
return out;
9310
}
9311
9312
+ obj.InvalidateNodeCache = function (user, mesh, nodeid) {
9313
+ if (user == null) { return; }
9314
+
9315
+ if (typeof user == 'string') { user = obj.users[user]; }
9316
+ if (user == null) { return 0; }
9317
+ var meshid;
9318
+ if (typeof mesh == 'string') { meshid = mesh; } else if ((typeof mesh == 'object') && (typeof mesh._id == 'string')) { meshid = mesh._id; };
9319
+
9320
+ if (mesh == null) {
9321
+ for (let [key, val] of Object.entries(GetNodeRightsCache[user._id] || {})) {
9322
+ GetNodeRightsCacheCount -= Object.keys(val).length
9323
+ }
9324
+ delete GetNodeRightsCache[user._id];
9325
+ return;
9326
+ }
9327
+ if (nodeid == null) {
9328
+ let cache_reduction = Object.keys((GetNodeRightsCache[user._id] || {})[meshid] || {}).length
9329
+ delete (GetNodeRightsCache[user._id] || {})[meshid]
9330
+ GetNodeRightsCacheCount -= cache_reduction;
9331
+ return;
9332
+ }
9333
+ if (((GetNodeRightsCache[user._id] || {})[meshid] || {})[nodeid]) {
9334
+ delete ((GetNodeRightsCache[user._id] || {})[meshid] || {})[nodeid]
9335
+ GetNodeRightsCacheCount--;
9336
+ }
9337
+ }
9338
+
9339
+ obj.FlushGetNodeRightsCache = function() {
9340
+ GetNodeRightsCache = {};
9341
+ GetNodeRightsCacheCount = 0;
9342
+ }
9343
+
9344
// Returns a list of displatch targets for a given mesh
9345
// We have to target the meshid and all user groups for this mesh, plus any added targets
9346
obj.CreateMeshDispatchTargets = function (mesh, addedTargets) {