mirror of
https://github.com/HeyPuter/puter.git
synced 2026-09-25 06:36:00 +00:00
update client-cache logic (#1626)
* client-cache: remove pulling * client-cache: fix wrong ts field * client-cache: purge cache on any local update * client-cache: last_updated_time -> last_valid_time * client-cache: update cache on remote update * client-cache: update last_valid_ts every sec * client-cache: switch to localstorage * do the cache and purge test when `setAuthToken` is called --------- Co-authored-by: Nariman Jelveh <nj@puter.com>
This commit is contained in:
co-authored by
Nariman Jelveh
parent
a0b567da52
commit
860388c3cb
@@ -2,7 +2,9 @@ import io from '../../lib/socket.io/socket.io.esm.min.js';
|
||||
import * as utils from '../../lib/utils.js';
|
||||
|
||||
// Constants
|
||||
const LAST_UPDATED_TS = 'last_updated_ts';
|
||||
//
|
||||
// The last valid time of the local cache.
|
||||
const LAST_VALID_TS = 'last_updated_ts';
|
||||
|
||||
// Operations
|
||||
import copy from './operations/copy.js';
|
||||
@@ -71,6 +73,7 @@ export class PuterJSFileSystemModule extends AdvancedBase {
|
||||
this.APIOrigin = context.APIOrigin;
|
||||
this.appID = context.appID;
|
||||
this.context = context;
|
||||
this.cacheUpdateTimer = null;
|
||||
// Connect socket.
|
||||
this.initializeSocket();
|
||||
|
||||
@@ -99,6 +102,9 @@ export class PuterJSFileSystemModule extends AdvancedBase {
|
||||
this.socket.disconnect();
|
||||
}
|
||||
|
||||
// Stop any existing cache update timer
|
||||
this.stopCacheUpdateTimer();
|
||||
|
||||
this.socket = io(this.APIOrigin, {
|
||||
auth: {
|
||||
auth_token: this.authToken,
|
||||
@@ -111,11 +117,7 @@ export class PuterJSFileSystemModule extends AdvancedBase {
|
||||
|
||||
bindSocketEvents() {
|
||||
this.socket.on('cache.updated', (item) => {
|
||||
const local_ts = puter._cache.get(LAST_UPDATED_TS);
|
||||
if (item.timestamp > local_ts || local_ts === undefined) {
|
||||
console.log(`remote timestamp (${item.timestamp}) is newer than local timestamp (${local_ts}), flushing cache`);
|
||||
puter._cache.flushall();
|
||||
}
|
||||
this.postUpdate();
|
||||
});
|
||||
|
||||
this.socket.on('connect', () => {
|
||||
@@ -130,10 +132,6 @@ export class PuterJSFileSystemModule extends AdvancedBase {
|
||||
{
|
||||
console.log('FileSystem Socket: Disconnected');
|
||||
}
|
||||
|
||||
// todo: NAIVE PURGE
|
||||
// purge cache on disconnect since we may have become out of sync
|
||||
puter._cache.flushall();
|
||||
});
|
||||
|
||||
this.socket.on('reconnect', (attempt) => {
|
||||
@@ -181,6 +179,14 @@ export class PuterJSFileSystemModule extends AdvancedBase {
|
||||
*/
|
||||
setAuthToken(authToken) {
|
||||
this.authToken = authToken;
|
||||
|
||||
// Check cache timestamp and purge if needed (only in GUI environment)
|
||||
if (this.context.env === 'gui') {
|
||||
this.checkCacheAndPurge();
|
||||
// Start background task to update LAST_VALID_TS every 1 second
|
||||
this.startCacheUpdateTimer();
|
||||
}
|
||||
|
||||
// reset socket
|
||||
this.initializeSocket();
|
||||
}
|
||||
@@ -199,15 +205,21 @@ export class PuterJSFileSystemModule extends AdvancedBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the last updated timestamp in the cache.
|
||||
* This should be called whenever file system operations modify the filesystem.
|
||||
* The cache-related actions after local and remote updates.
|
||||
*
|
||||
* @memberof PuterJSFileSystemModule
|
||||
* @returns {void}
|
||||
*/
|
||||
updateCacheTimestamp() {
|
||||
// Add 1 second to mitigate clock skew and disable self-update.
|
||||
puter._cache.set(LAST_UPDATED_TS, Date.now() + 1000);
|
||||
postUpdate() {
|
||||
// Action: Flush local cache
|
||||
puter._cache.flushall();
|
||||
|
||||
// Action: Update last valid time
|
||||
//
|
||||
// Set to 0, which means the cache is not up to date.
|
||||
localStorage.setItem(LAST_VALID_TS, '0');
|
||||
|
||||
console.log(`postUpdate triggered, LAST_VALID_TS: ${localStorage.getItem(LAST_VALID_TS)}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -233,4 +245,64 @@ export class PuterJSFileSystemModule extends AdvancedBase {
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks cache timestamp and purges cache if needed.
|
||||
* Only runs in GUI environment.
|
||||
*
|
||||
* @memberof PuterJSFileSystemModule
|
||||
* @returns {void}
|
||||
*/
|
||||
async checkCacheAndPurge() {
|
||||
try {
|
||||
const serverTimestamp = await this.getCacheTimestamp();
|
||||
const localValidTs = parseInt(localStorage.getItem(LAST_VALID_TS)) || 0;
|
||||
|
||||
console.log(`init comparison: serverTimestamp: ${serverTimestamp}, localValidTs: ${localValidTs}`);
|
||||
if (serverTimestamp > localValidTs) {
|
||||
console.log(`serverTimestamp > localValidTs, purging cache`);
|
||||
// Server has newer data, purge local cache
|
||||
puter._cache.flushall();
|
||||
localStorage.setItem(LAST_VALID_TS, '0');
|
||||
}
|
||||
} catch (error) {
|
||||
// If we can't get the server timestamp, silently fail
|
||||
// This ensures the socket initialization doesn't break
|
||||
console.error('Error checking cache timestamp:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the background task to update LAST_VALID_TS every 1 second.
|
||||
* Only runs in GUI environment.
|
||||
*
|
||||
* @memberof PuterJSFileSystemModule
|
||||
* @returns {void}
|
||||
*/
|
||||
startCacheUpdateTimer() {
|
||||
if (this.context.env !== 'gui') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear any existing timer
|
||||
this.stopCacheUpdateTimer();
|
||||
|
||||
// Start new timer
|
||||
this.cacheUpdateTimer = setInterval(() => {
|
||||
localStorage.setItem(LAST_VALID_TS, Date.now().toString());
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the background cache update timer.
|
||||
*
|
||||
* @memberof PuterJSFileSystemModule
|
||||
* @returns {void}
|
||||
*/
|
||||
stopCacheUpdateTimer() {
|
||||
if (this.cacheUpdateTimer) {
|
||||
clearInterval(this.cacheUpdateTimer);
|
||||
this.cacheUpdateTimer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,10 +56,7 @@ const copy = function (...args) {
|
||||
dedupe_name: (options.dedupe_name || options.dedupeName),
|
||||
}));
|
||||
|
||||
this.updateCacheTimestamp();
|
||||
|
||||
// TOOD (xiaochen): puter desktop will have stale cache without this, find out why
|
||||
puter._cache.flushall();
|
||||
this.postUpdate();
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -54,10 +54,7 @@ const mkdir = function (...args) {
|
||||
create_missing_parents: (options.recursive || options.createMissingParents) ?? false,
|
||||
}));
|
||||
|
||||
this.updateCacheTimestamp();
|
||||
|
||||
// TOOD (xiaochen): puter desktop will have stale cache without this, find out why
|
||||
puter._cache.flushall();
|
||||
this.postUpdate();
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -66,10 +66,7 @@ const move = function (...args) {
|
||||
original_client_socket_id: options.excludeSocketID,
|
||||
}));
|
||||
|
||||
this.updateCacheTimestamp();
|
||||
|
||||
// TOOD (xiaochen): puter desktop will have stale cache without this, find out why
|
||||
puter._cache.flushall();
|
||||
this.postUpdate();
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -51,10 +51,7 @@ const rename = function (...args) {
|
||||
|
||||
xhr.send(JSON.stringify(dataToSend));
|
||||
|
||||
this.updateCacheTimestamp();
|
||||
|
||||
// TOOD (xiaochen): puter desktop will have stale cache without this, find out why
|
||||
puter._cache.flushall();
|
||||
this.postUpdate();
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -432,10 +432,7 @@ const upload = async function(items, dirPath, options = {}){
|
||||
// send request
|
||||
xhr.send(fd);
|
||||
|
||||
this.updateCacheTimestamp();
|
||||
|
||||
// TOOD (xiaochen): puter desktop will have stale cache without this, find out why
|
||||
puter._cache.flushall();
|
||||
this.postUpdate();
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -55,10 +55,7 @@ const write = async function (targetPath, data, options = {}) {
|
||||
throw new Error({ code: 'field_invalid', message: 'write() data parameter is an invalid type' });
|
||||
}
|
||||
|
||||
this.updateCacheTimestamp();
|
||||
|
||||
// TOOD (xiaochen): puter desktop will have stale cache without this, find out why
|
||||
puter._cache.flushall();
|
||||
this.postUpdate();
|
||||
|
||||
// perform upload
|
||||
return this.upload(data, parent, options);
|
||||
|
||||
Reference in New Issue
Block a user