Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bust RunTimeline cache #23482

Merged
merged 4 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,38 @@ export const defaultOptions = {
expiry: new Date('3030-01-01'), // never expire,
};

type CacheType<T> = {
version: string | number;
cache: InstanceType<typeof HourlyDataCache<T>>['cache'];
};

export class HourlyDataCache<T> {
private cache: Map<number, Array<TimeWindow<T>>> = new Map();
private subscriptions: Array<{hour: number; callback: Subscription<T>}> = [];
private indexedDBCache?: ReturnType<typeof cache<string, typeof this.cache>>;
private indexedDBCache?: ReturnType<typeof cache<string, CacheType<T>>>;
private indexedDBKey: string;
private version: string | number;

/**
* @param id A unique ID for the hourly data cache in this deployment
* @param [keyPrefix=''] A unique key identifying the timeline view [incorporating filters, etc.]
*/
constructor(id?: string | false, keyPrefix = '', keyMaxCount = 1) {
constructor({
id,
keyPrefix = '',
keyMaxCount = 1,
version = '-1',
}: {
id?: string | false;
keyPrefix?: string;
keyMaxCount?: number;
version?: string | number;
}) {
this.version = version;
this.indexedDBKey = keyPrefix ? `${keyPrefix}-hourlyData` : 'hourlyData';

// Delete old database from before the prefix, remove this at some point
indexedDB.deleteDatabase('HourlyDataCache:useRunsForTimeline');

if (id) {
this.indexedDBCache = cache<string, typeof this.cache>({
this.indexedDBCache = cache<string, CacheType<T>>({
dbName: `HourlyDataCache:${id}`,
maxCount: keyMaxCount,
});
Expand All @@ -54,8 +68,8 @@ export class HourlyDataCache<T> {
return;
}
const cachedData = await this.indexedDBCache.get(this.indexedDBKey);
if (cachedData) {
this.cache = new Map(cachedData.value);
if (cachedData && cachedData.value.version === this.version) {
this.cache = new Map(cachedData.value.cache);
}
res();
});
Expand All @@ -69,23 +83,35 @@ export class HourlyDataCache<T> {
if (!this.indexedDBCache) {
return;
}
this.indexedDBCache.set(this.indexedDBKey, this.cache, defaultOptions);
this.indexedDBCache.set(
this.indexedDBKey,
{version: this.version, cache: this.cache},
defaultOptions,
);
return;
}
clearTimeout(this.saveTimeout);
this.saveTimeout = setTimeout(() => {
if (!this.indexedDBCache) {
return;
}
this.indexedDBCache.set(this.indexedDBKey, this.cache, defaultOptions);
this.indexedDBCache.set(
this.indexedDBKey,
{version: this.version, cache: this.cache},
defaultOptions,
);
}, 10000);
if (!this.registeredUnload) {
this.registeredUnload = true;
window.addEventListener('beforeunload', () => {
if (!this.indexedDBCache) {
return;
}
this.indexedDBCache.set(this.indexedDBKey, this.cache, defaultOptions);
this.indexedDBCache.set(
this.indexedDBKey,
{version: this.version, cache: this.cache},
defaultOptions,
);
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,17 @@ export const useRunsForTimeline = ({
const {localCacheIdPrefix} = useContext(AppContext);
const completedRunsCache = useMemo(() => {
if (filter) {
return new HourlyDataCache<RunTimelineFragment>(
localCacheIdPrefix ? `${localCacheIdPrefix}-useRunsForTimeline-filtered` : false,
JSON.stringify(filter),
3,
);
return new HourlyDataCache<RunTimelineFragment>({
id: localCacheIdPrefix ? `${localCacheIdPrefix}-useRunsForTimeline-filtered` : false,
keyPrefix: JSON.stringify(filter),
keyMaxCount: 3,
version: 1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Track this value in a single module-level const (with a loud comment?) so that we don't miss changing it in both places?

});
}
return new HourlyDataCache<RunTimelineFragment>(
localCacheIdPrefix ? `${localCacheIdPrefix}-useRunsForTimeline` : false,
);
return new HourlyDataCache<RunTimelineFragment>({
id: localCacheIdPrefix ? `${localCacheIdPrefix}-useRunsForTimeline` : false,
version: 1,
});
}, [filter, localCacheIdPrefix]);
const [completedRuns, setCompletedRuns] = useState<RunTimelineFragment[]>([]);

Expand Down