From 7382264648da7145bad4397e7463d93b2ec0986e Mon Sep 17 00:00:00 2001 From: Nariman Jelveh Date: Sun, 28 Sep 2025 20:35:51 -0700 Subject: [PATCH] more nuanced cache invalidation strategy with logging enabled by default --- src/puter-js/src/modules/FileSystem/index.js | 75 +++++++++++++++---- .../modules/FileSystem/operations/mkdir.js | 2 +- .../modules/FileSystem/operations/readdir.js | 5 +- .../modules/FileSystem/operations/rename.js | 3 +- 4 files changed, 65 insertions(+), 20 deletions(-) diff --git a/src/puter-js/src/modules/FileSystem/index.js b/src/puter-js/src/modules/FileSystem/index.js index 532d5be2b..f525b631c 100644 --- a/src/puter-js/src/modules/FileSystem/index.js +++ b/src/puter-js/src/modules/FileSystem/index.js @@ -25,6 +25,8 @@ import { AdvancedBase } from '../../../../putility/index.js'; import FSItem from '../FSItem.js'; import deleteFSEntry from './operations/deleteFSEntry.js'; import getReadURL from './operations/getReadUrl.js'; +import path from "../../lib/path.js"; + export class PuterJSFileSystemModule extends AdvancedBase { @@ -113,21 +115,50 @@ export class PuterJSFileSystemModule extends AdvancedBase { } bindSocketEvents() { - this.socket.on('cache.updated', (msg) => { - // check original_client_socket_id and if it matches this.socket.id, don't post update - if (msg.original_client_socket_id !== this.socket.id) { - this.invalidateCache(); + // this.socket.on('cache.updated', (msg) => { + // // check original_client_socket_id and if it matches this.socket.id, don't post update + // if (msg.original_client_socket_id !== this.socket.id) { + // this.invalidateCache(); + // } + // }); + + this.socket.on('item.renamed', (item) => { + // check original_client_socket_id and if it matches this.socket.id, don't invalidate cache + if (item.original_client_socket_id !== this.socket.id) { + this.invalidateCache(item); } }); - // item.renamed is triggered when a file is renamed, this is a quirk since right now cache.updated is not triggered when a file is renamed! - this.socket.on('item.renamed', (item) => { - // check original_client_socket_id and if it matches this.socket.id, don't post update + this.socket.on('item.deleted', (item) => { + // check original_client_socket_id and if it matches this.socket.id, don't invalidate cache if (item.original_client_socket_id !== this.socket.id) { - this.invalidateCache(); + this.invalidateCache(item); } }); + this.socket.on('item.added', (item) => { + // check original_client_socket_id and if it matches this.socket.id, don't invalidate cache + if (item.original_client_socket_id !== this.socket.id) { + this.invalidateCache(item); + } + }); + + this.socket.on('item.updated', (item) => { + // check original_client_socket_id and if it matches this.socket.id, don't invalidate cache + if (item.original_client_socket_id !== this.socket.id) { + this.invalidateCache(item); + } + }); + + this.socket.on('item.moved', (item) => { + // check original_client_socket_id and if it matches this.socket.id, don't invalidate cache + if (item.original_client_socket_id !== this.socket.id) { + this.invalidateCache(item); + } + }); + + + this.socket.on('connect', () => { if ( puter.debugMode ) { @@ -218,15 +249,31 @@ export class PuterJSFileSystemModule extends AdvancedBase { * @memberof PuterJSFileSystemModule * @returns {void} */ - invalidateCache() { - // Action: Flush local cache - puter._cache.flushall(); - console.log('invalidateCache triggered, cache flushed'); - + invalidateCache(item) { // Action: Update last valid time - // // Set to 0, which means the cache is not up to date. localStorage.setItem(LAST_VALID_TS, '0'); + + // Action: Update cache for the item + if(item?.path){ + console.log('invalidated cache for item:', item.path); + // update cache for the item + puter._cache.set('item:' + item.path, item); + + // if item is a folder, invalidate the readdir cache for the folder + if(item.is_dir){ + puter._cache.del('readdir:' + item.path); + console.log('⮑ invalidated its readdir:', item.path); + } + // invalidate parent folder cache + puter._cache.del('readdir:' + path.dirname(item.path)); + console.log('⮑ invalidated its parent readdir:', path.dirname(item.path)); + + + }else{ + puter._cache.flushall(); + console.log('invalidated cache for all items'); + } } /** diff --git a/src/puter-js/src/modules/FileSystem/operations/mkdir.js b/src/puter-js/src/modules/FileSystem/operations/mkdir.js index 8e7a411f8..2fabce36f 100644 --- a/src/puter-js/src/modules/FileSystem/operations/mkdir.js +++ b/src/puter-js/src/modules/FileSystem/operations/mkdir.js @@ -54,7 +54,7 @@ const mkdir = function (...args) { create_missing_parents: (options.recursive || options.createMissingParents) ?? false, })); - this.invalidateCache(); + this.invalidateCache(options.path); }) } diff --git a/src/puter-js/src/modules/FileSystem/operations/readdir.js b/src/puter-js/src/modules/FileSystem/operations/readdir.js index 54b3051e7..4a0ee9b81 100644 --- a/src/puter-js/src/modules/FileSystem/operations/readdir.js +++ b/src/puter-js/src/modules/FileSystem/operations/readdir.js @@ -31,8 +31,6 @@ const readdir = async function (...args) { let cacheKey; if(options.path){ cacheKey = 'readdir:' + options.path; - }else if(options.uid){ - cacheKey = 'readdir:' + options.uid; } if(options.consistency === 'eventual'){ @@ -64,7 +62,7 @@ const readdir = async function (...args) { const resultSize = JSON.stringify(result).length; // Cache the result if it's not bigger than MAX_CACHE_SIZE - const MAX_CACHE_SIZE = 20 * 1024 * 1024; + const MAX_CACHE_SIZE = 100 * 1024 * 1024; if(resultSize <= MAX_CACHE_SIZE){ // UPSERT the cache @@ -73,7 +71,6 @@ const readdir = async function (...args) { // set each individual item's cache for(const item of result){ - await puter._cache.set('item:' + item.id, item); await puter._cache.set('item:' + item.path, item); } diff --git a/src/puter-js/src/modules/FileSystem/operations/rename.js b/src/puter-js/src/modules/FileSystem/operations/rename.js index ff377ecfc..adefd2aa3 100644 --- a/src/puter-js/src/modules/FileSystem/operations/rename.js +++ b/src/puter-js/src/modules/FileSystem/operations/rename.js @@ -47,11 +47,12 @@ const rename = function (...args) { // If dirPath is not provided or it's not starting with a slash, it means it's a relative path // in that case, we need to prepend the app's root directory to it dataToSend.path = getAbsolutePathForApp(options.path); + + this.invalidateCache(dataToSend.path); } xhr.send(JSON.stringify(dataToSend)); - this.invalidateCache(); }) }