sw: add expiration to preview

cap
Varun Patil 2022-12-07 22:06:27 -08:00
parent 254672fabe
commit 92c35339f3
1 changed files with 32 additions and 4 deletions

View File

@ -1,5 +1,7 @@
import { registerRoute } from "workbox-routing";
import { CacheExpiration } from "workbox-expiration";
// Queue of requests to fetch preview images
interface FetchPreviewObject {
url: URL;
fileid: number;
@ -8,11 +10,20 @@ interface FetchPreviewObject {
}
let fetchPreviewQueue: FetchPreviewObject[] = [];
// Cache for preview images
const cacheName = "images";
let imageCache: Cache;
(async () => {
imageCache = await caches.open("images");
imageCache = await caches.open(cacheName);
})();
// Expiration for cache
const expirationManager = new CacheExpiration(cacheName, {
maxAgeSeconds: 3600 * 24 * 7, // days
maxEntries: 20000, // 20k images
});
// Start fetching with multipreview
let fetchPreviewTimer: any;
async function flushPreviewQueue() {
if (fetchPreviewQueue.length === 0) return;
@ -21,6 +32,13 @@ async function flushPreviewQueue() {
const fetchPreviewQueueCopy = fetchPreviewQueue;
fetchPreviewQueue = [];
// Check if only one request
if (fetchPreviewQueueCopy.length === 1) {
const p = fetchPreviewQueueCopy[0];
return p.callback(await fetch(p.url));
}
// Create aggregated request body
const files = fetchPreviewQueueCopy.map((p) => ({
fileid: p.fileid,
x: Number(p.url.searchParams.get("x")),
@ -41,11 +59,13 @@ async function flushPreviewQueue() {
url.searchParams.delete("a");
url.searchParams.delete("c");
// Fetch multipreview
const res = await fetch(url, {
method: "POST",
body: JSON.stringify(files),
});
// Get blob
if (res.status !== 200) throw new Error("Error fetching multi-preview");
const blob = await res.blob();
@ -85,7 +105,7 @@ async function flushPreviewQueue() {
});
}
} catch (e) {
console.error(e);
console.error("Multipreview error", e);
}
// Initiate callbacks for failed requests
@ -99,9 +119,10 @@ async function flushPreviewQueue() {
});
}
// Intercept preview requests
registerRoute(
/^.*\/apps\/memories\/api\/image\/preview\/.*/,
async ({ url }) => {
async ({ url, request }) => {
// Check if in cache
const cache = await imageCache?.match(url);
if (cache) return cache;
@ -122,13 +143,20 @@ registerRoute(
}
});
// Fallback to single request
if (res.status !== 200) {
res = await fetch(url);
}
// Cache response
if (res.status === 200) {
imageCache?.put(url, res.clone());
imageCache?.put(request, res.clone());
expirationManager.updateTimestamp(request.url);
}
// Run expiration once in every 20 requests
if (Math.random() < 0.05) {
expirationManager.expireEntries();
}
return res;