Picsur/frontend/src/app/services/storage/cache.service.ts

83 lines
1.8 KiB
TypeScript
Raw Normal View History

2022-05-09 15:02:59 +00:00
import { Inject, Injectable } from '@angular/core';
import { SESSION_STORAGE } from '@ng-web-apis/common';
2022-03-30 09:40:50 +00:00
import { AsyncFailable, Failable, HasFailed } from 'picsur-shared/dist/types';
2022-03-24 18:56:26 +00:00
interface dataWrapper<T> {
data: T;
expires: number;
}
@Injectable({
providedIn: 'root',
})
export class CacheService {
private readonly cacheExpiresMS = 1000 * 60 * 60;
2022-09-11 14:09:19 +00:00
private cacheVersion = '0.0.0';
2022-03-24 18:56:26 +00:00
2022-05-09 15:02:59 +00:00
constructor(@Inject(SESSION_STORAGE) private readonly storage: Storage) {}
2022-03-24 18:56:26 +00:00
2022-09-11 14:09:19 +00:00
public setVersion(version: string): void {
if (version !== this.cacheVersion) this.clear();
this.cacheVersion = version;
}
public clear(): void {
this.storage.clear();
}
2022-03-30 09:40:50 +00:00
public set<T>(key: string, value: T): void {
2022-09-11 14:09:19 +00:00
const safeKey = this.transformKey(key);
2022-03-30 09:40:50 +00:00
const data: dataWrapper<T> = {
data: value,
expires: Date.now() + this.cacheExpiresMS,
};
2022-09-11 14:09:19 +00:00
this.storage.setItem(safeKey, JSON.stringify(data));
2022-03-30 09:40:50 +00:00
}
2022-03-24 18:56:26 +00:00
public get<T>(key: string): T | null {
2022-09-11 14:09:19 +00:00
const safeKey = this.transformKey(key);
2022-03-24 18:56:26 +00:00
try {
2022-12-25 21:35:04 +00:00
const data: dataWrapper<T> = JSON.parse(
this.storage.getItem(safeKey) ?? '',
);
2022-03-24 18:56:26 +00:00
if (data && data.data && data.expires > Date.now()) {
return data.data;
}
return null;
} catch (e) {
return null;
}
}
2022-03-30 09:40:50 +00:00
public async getFallback<T>(
key: string,
finalFallback: T,
...fallbacks: Array<(key: string) => AsyncFailable<T> | Failable<T>>
): Promise<T> {
2022-09-11 14:22:37 +00:00
const cached = this.get<T>(key);
2022-03-30 09:40:50 +00:00
if (cached !== null) {
return cached;
}
2022-03-24 18:56:26 +00:00
2022-03-30 09:40:50 +00:00
for (const fallback of fallbacks) {
2022-09-11 14:22:37 +00:00
const result = await fallback(key);
2022-03-30 09:40:50 +00:00
if (HasFailed(result)) {
continue;
}
2022-09-11 14:22:37 +00:00
this.set(key, result);
2022-03-30 09:40:50 +00:00
return result;
}
return finalFallback;
2022-03-24 18:56:26 +00:00
}
2022-09-11 14:09:19 +00:00
private transformKey(key: string): string {
return `${this.cacheVersion}-${key}`;
}
2022-03-24 18:56:26 +00:00
}