typedserver/ts_web_serviceworker/classes.updatemanager.ts
2024-05-25 01:24:02 +02:00

92 lines
3.5 KiB
TypeScript

import * as plugins from './plugins.js';
import * as interfaces from '../dist_ts_interfaces/index.js';
import { ServiceWorker } from './classes.serviceworker.js';
import { logger } from './logging.js';
import { CacheManager } from './classes.cachemanager.js';
export class UpdateManager {
public lastUpdateCheck: number = 0;
public lastVersionInfo: interfaces.serviceworker.IRequest_Serviceworker_Backend_VersionInfo['response'];
public serviceworkerRef: ServiceWorker;
constructor(serviceWorkerRefArg: ServiceWorker) {
this.serviceworkerRef = serviceWorkerRefArg;
}
/**
* checks wether an update is needed
*/
public async checkUpdate(cacheManager: CacheManager): Promise<boolean> {
const lswVersionInfoKey = 'versionInfo';
if (!this.lastVersionInfo && !(await this.serviceworkerRef.store.check(lswVersionInfoKey))) {
this.lastVersionInfo = {
appHash: '',
appSemVer: 'v0.0.0',
};
} else if (
!this.lastVersionInfo &&
(await this.serviceworkerRef.store.check(lswVersionInfoKey))
) {
this.lastVersionInfo = await this.serviceworkerRef.store.get(lswVersionInfoKey);
}
const now = Date.now();
const millisSinceLastCheck = now - this.lastUpdateCheck;
if (millisSinceLastCheck < 100000) {
// TODO account for being offline
return false;
}
logger.log('info', 'checking for update of the app by comparing app hashes...');
this.lastUpdateCheck = now;
const currentVersionInfo = await this.getVersionInfoFromServer();
logger.log('info', `old versionInfo: ${JSON.stringify(this.lastVersionInfo)}`);
logger.log('info', `current versionInfo: ${JSON.stringify(currentVersionInfo)}`);
const needsUpdate = this.lastVersionInfo.appHash !== currentVersionInfo.appHash ? true : false;
if (needsUpdate) {
logger.log('info', 'Caches need to be updated');
logger.log('info', 'starting a debounced update task');
this.performAsyncUpdateDebouncedTask.trigger();
this.lastVersionInfo = currentVersionInfo;
await this.serviceworkerRef.store.set(lswVersionInfoKey, this.lastVersionInfo);
} else {
logger.log('ok', 'caches are still valid, performing revalidation in a bit...');
this.performAsyncCacheRevalidationDebouncedTask.trigger();
}
}
/**
* gets the apphash from the server
*/
public async getVersionInfoFromServer() {
const getAppHashRequest = new plugins.typedrequest.TypedRequest<
interfaces.serviceworker.IRequest_Serviceworker_Backend_VersionInfo
>('/sw-typedrequest', 'serviceworker_versionInfo');
const result = await getAppHashRequest.fire({});
return result;
}
// tasks
/**
* this task is executed once we know that there is a new version available
*/
public performAsyncUpdateDebouncedTask = new plugins.taskbuffer.TaskDebounced({
name: 'performAsyncUpdate',
taskFunction: async () => {
logger.log('info', 'trying to update PWA with serviceworker');
await this.serviceworkerRef.cacheManager.cleanCaches('a new app version has been communicated by the server.');
// lets notify all current clients about the update
await this.serviceworkerRef.leleServiceWorkerBackend.triggerReloadAll();
},
debounceTimeInMillis: 2000,
});
public performAsyncCacheRevalidationDebouncedTask = new plugins.taskbuffer.TaskDebounced({
name: 'performAsyncCacheRevalidation',
taskFunction: async () => {
await this.serviceworkerRef.cacheManager.revalidateCache();
},
debounceTimeInMillis: 6000
});
}