122 lines
3.7 KiB
TypeScript
122 lines
3.7 KiB
TypeScript
import * as plugins from './levelcache.plugins.js';
|
|
import { CacheDiskManager } from './levelcache.classes.cache.diskmanager.js';
|
|
import { CacheMemoryManager } from './levelcache.classes.cache.memorymanager.js';
|
|
import { CacheS3Manager } from './levelcache.classes.cache.s3manager.js';
|
|
import { CacheEntry } from './levelcache.classes.cacheentry.js';
|
|
import { CacheRouter } from './levelcache.classes.cacherouter.js';
|
|
import { AbstractCache } from './levelcache.abstract.classes.cache.js';
|
|
|
|
export interface ILevelCacheConstructorOptions {
|
|
/**
|
|
* a unique id when having more than one cache
|
|
*/
|
|
cacheId: string;
|
|
maxMemoryStorageInMB?: number;
|
|
maxDiskStorageInMB?: number;
|
|
maxS3StorageInMB?: number;
|
|
diskStoragePath?: string;
|
|
s3Config?: plugins.tsclass.storage.IS3Descriptor;
|
|
s3BucketName?: string;
|
|
forceLevel?: 'memory' | 'disk' | 's3';
|
|
expirationInMs?: number;
|
|
immutableCache?: boolean;
|
|
persistentCache?: boolean;
|
|
}
|
|
|
|
/**
|
|
* a leveled cache for storing things for a short time
|
|
*/
|
|
export class LevelCache extends AbstractCache {
|
|
private readyDeferred = plugins.smartpromise.defer<void>();
|
|
|
|
public ready = this.readyDeferred.promise;
|
|
|
|
public status: 'active' = 'active'; // artifact of AbstractCache
|
|
|
|
public cacheRouter = new CacheRouter(this);
|
|
public cacheDiskManager: CacheDiskManager;
|
|
public cacheMemoryManager: CacheMemoryManager;
|
|
public cacheS3Manager: CacheS3Manager;
|
|
|
|
public options: ILevelCacheConstructorOptions;
|
|
|
|
constructor(optionsArg: ILevelCacheConstructorOptions) {
|
|
super();
|
|
this.options = {
|
|
maxMemoryStorageInMB: 0.5,
|
|
maxDiskStorageInMB: 10,
|
|
maxS3StorageInMB: 50,
|
|
...optionsArg,
|
|
};
|
|
this.init();
|
|
}
|
|
|
|
public async init() {
|
|
this.cacheMemoryManager = new CacheMemoryManager(this);
|
|
this.cacheDiskManager = new CacheDiskManager(this);
|
|
this.cacheS3Manager = new CacheS3Manager(this);
|
|
await Promise.all([
|
|
this.cacheDiskManager.ready,
|
|
this.cacheMemoryManager.ready,
|
|
this.cacheS3Manager.ready,
|
|
]);
|
|
this.readyDeferred.resolve();
|
|
}
|
|
|
|
// store things
|
|
public async storeCacheEntryByKey(keyArg: string, cacheEntryArg: CacheEntry): Promise<void> {
|
|
cacheEntryArg.key = keyArg;
|
|
const targetCache = await this.cacheRouter.getCacheForStoreAction(keyArg, cacheEntryArg);
|
|
cacheEntryArg.createdAt = Date.now();
|
|
await targetCache.storeCacheEntryByKey(keyArg, cacheEntryArg);
|
|
}
|
|
|
|
// retrieve things
|
|
/**
|
|
* retrieve cache entry
|
|
*/
|
|
public async retrieveCacheEntryByKey(keyArg: string): Promise<CacheEntry> {
|
|
const targetCache = await this.cacheRouter.getCacheForRetrieveAction(keyArg);
|
|
if (targetCache) {
|
|
const cacheEntry = await targetCache.retrieveCacheEntryByKey(keyArg);
|
|
if (cacheEntry.createdAt + cacheEntry.ttl < Date.now()) {
|
|
await this.deleteCacheEntryByKey(keyArg).catch();
|
|
return null;
|
|
}
|
|
return cacheEntry;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public async checkKeyPresence(keyArg: string): Promise<boolean> {
|
|
return plugins.smartpromise.getFirstTrueOrFalse([
|
|
this.cacheMemoryManager.checkKeyPresence(keyArg),
|
|
this.cacheDiskManager.checkKeyPresence(keyArg),
|
|
this.cacheS3Manager.checkKeyPresence(keyArg),
|
|
]);
|
|
}
|
|
|
|
public async deleteCacheEntryByKey(keyArg) {
|
|
await Promise.all([
|
|
this.cacheMemoryManager.deleteCacheEntryByKey(keyArg),
|
|
this.cacheDiskManager.deleteCacheEntryByKey(keyArg),
|
|
this.cacheS3Manager.deleteCacheEntryByKey(keyArg),
|
|
]);
|
|
}
|
|
|
|
// cache maintenance
|
|
public async cleanOutdated() {}
|
|
|
|
/**
|
|
* cleans the complete cache
|
|
*/
|
|
public async cleanAll(): Promise<void> {
|
|
await Promise.all([
|
|
this.cacheDiskManager.cleanAll(),
|
|
this.cacheDiskManager.cleanAll(),
|
|
this.cacheS3Manager.cleanAll(),
|
|
]);
|
|
}
|
|
}
|