ximg: move cache to main thread

Signed-off-by: Varun Patil <varunpatil@ucla.edu>
pull/563/head
Varun Patil 2023-04-12 20:34:59 -07:00
parent 7a316785fa
commit a01092f3ae
2 changed files with 53 additions and 48 deletions

View File

@ -7,8 +7,7 @@ const worker = new Worker(new URL("./XImgWorker.ts", import.meta.url));
// Import worker functions
const importer = workerImporter(worker);
export const fetchImage = importer<typeof w.fetchImageSrc>("fetchImageSrc");
export const sticky = importer<typeof w.sticky>("sticky");
const fetchImageSrc = importer<typeof w.fetchImageSrc>("fetchImageSrc");
// Configure worker on startup
document.addEventListener("DOMContentLoaded", () =>
@ -16,3 +15,53 @@ document.addEventListener("DOMContentLoaded", () =>
multiUrl: API.IMAGE_MULTIPREVIEW(),
})
);
// Memcache for blob URLs
const BLOB_CACHE = new Map<string, object>() as Map<string, [number, string]>;
const BLOB_STICKY = new Map<string, number>();
// Periodic blob cache cleaner
window.setInterval(() => {
for (const [src, cache] of BLOB_CACHE.entries()) {
// Skip if sticky
if (BLOB_STICKY.has(cache[1])) {
cache[0] = 30; // reset timer
continue;
}
// Decrement timer and revoke if expired
if ((cache[0] -= 3) <= 0) {
URL.revokeObjectURL(cache[1]);
BLOB_CACHE.delete(src);
}
}
}, 3000);
/** Change stickiness for a BLOB url */
export async function sticky(url: string, delta: number) {
if (!BLOB_STICKY.has(url)) BLOB_STICKY.set(url, 0);
const val = BLOB_STICKY.get(url) + delta;
if (val <= 0) {
BLOB_STICKY.delete(url);
} else {
BLOB_STICKY.set(url, val);
}
}
export async function fetchImage(url: string) {
// Check memcache entry
if (BLOB_CACHE.has(url)) return BLOB_CACHE.get(url)[1];
// Fetch image
const blobUrl = await fetchImageSrc(url);
// Check memcache entry again and revoke if it was added in the meantime
if (BLOB_CACHE.has(url)) {
URL.revokeObjectURL(blobUrl);
return BLOB_CACHE.get(url)[1];
}
// Create new memecache entry
BLOB_CACHE.set(url, [30, blobUrl]); // 30s expiration
return blobUrl;
}

View File

@ -1,27 +1,6 @@
import { CacheExpiration } from "workbox-expiration";
import { workerExport } from "../../worker";
// Memcache for blob URLs
const BLOB_CACHE = new Map<string, object>() as Map<string, [number, string]>;
const BLOB_STICKY = new Map<string, number>();
// Periodic blob cache cleaner
self.setInterval(() => {
for (const [src, cache] of BLOB_CACHE.entries()) {
// Skip if sticky
if (BLOB_STICKY.has(cache[1])) {
cache[0] = 30; // reset timer
continue;
}
// Decrement timer and revoke if expired
if ((cache[0] -= 3) <= 0) {
URL.revokeObjectURL(cache[1]);
BLOB_CACHE.delete(src);
}
}
}, 3000);
type BlobCallback = {
resolve: (blob: Blob) => void;
reject: (err: Error) => void;
@ -322,31 +301,8 @@ export async function configure(_config: typeof config) {
/** Get BLOB url for image */
export async function fetchImageSrc(url: string) {
// Check memcache entry
if (BLOB_CACHE.has(url)) return BLOB_CACHE.get(url)[1];
// Fetch image
const blob = await fetchImage(url);
// Check memcache entry again (in case it was added while fetching)
if (BLOB_CACHE.has(url)) return BLOB_CACHE.get(url)[1];
// Create new memecache entry
const blobUrl = URL.createObjectURL(blob);
BLOB_CACHE.set(url, [30, blobUrl]); // 30s expiration
return blobUrl;
}
/** Change stickiness for a BLOB url */
export async function sticky(url: string, delta: number) {
if (!BLOB_STICKY.has(url)) BLOB_STICKY.set(url, 0);
const val = BLOB_STICKY.get(url) + delta;
if (val <= 0) {
BLOB_STICKY.delete(url);
} else {
BLOB_STICKY.set(url, val);
}
return URL.createObjectURL(await fetchImage(url));
}
// Exports to main thread
workerExport({ fetchImageSrc, configure, sticky });
workerExport({ fetchImageSrc, configure });