ximg: move cache to main thread
Signed-off-by: Varun Patil <varunpatil@ucla.edu>pull/563/head
parent
7a316785fa
commit
a01092f3ae
|
@ -7,8 +7,7 @@ const worker = new Worker(new URL("./XImgWorker.ts", import.meta.url));
|
||||||
|
|
||||||
// Import worker functions
|
// Import worker functions
|
||||||
const importer = workerImporter(worker);
|
const importer = workerImporter(worker);
|
||||||
export const fetchImage = importer<typeof w.fetchImageSrc>("fetchImageSrc");
|
const fetchImageSrc = importer<typeof w.fetchImageSrc>("fetchImageSrc");
|
||||||
export const sticky = importer<typeof w.sticky>("sticky");
|
|
||||||
|
|
||||||
// Configure worker on startup
|
// Configure worker on startup
|
||||||
document.addEventListener("DOMContentLoaded", () =>
|
document.addEventListener("DOMContentLoaded", () =>
|
||||||
|
@ -16,3 +15,53 @@ document.addEventListener("DOMContentLoaded", () =>
|
||||||
multiUrl: API.IMAGE_MULTIPREVIEW(),
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -1,27 +1,6 @@
|
||||||
import { CacheExpiration } from "workbox-expiration";
|
import { CacheExpiration } from "workbox-expiration";
|
||||||
import { workerExport } from "../../worker";
|
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 = {
|
type BlobCallback = {
|
||||||
resolve: (blob: Blob) => void;
|
resolve: (blob: Blob) => void;
|
||||||
reject: (err: Error) => void;
|
reject: (err: Error) => void;
|
||||||
|
@ -322,31 +301,8 @@ export async function configure(_config: typeof config) {
|
||||||
|
|
||||||
/** Get BLOB url for image */
|
/** Get BLOB url for image */
|
||||||
export async function fetchImageSrc(url: string) {
|
export async function fetchImageSrc(url: string) {
|
||||||
// Check memcache entry
|
return URL.createObjectURL(await fetchImage(url));
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exports to main thread
|
// Exports to main thread
|
||||||
workerExport({ fetchImageSrc, configure, sticky });
|
workerExport({ fetchImageSrc, configure });
|
||||||
|
|
Loading…
Reference in New Issue