Workaround for broken cache expiry handling (#47)
Deno's cache API does not respect expiry dates. This meant that feeds were cached much longer than intended. This PR implments a manual cache handling instead of relying on Deno's implementation. Relevant issue: https://github.com/denoland/deno/issues/25795
This commit is contained in:
parent
a17798fe64
commit
b2c8662861
|
|
@ -27,6 +27,7 @@ export function responseXML(body: string, status: Status) {
|
|||
export const withExpiry = <T>(response: Response, ttlInSeconds: number) => {
|
||||
const clonedResponse = response.clone();
|
||||
clonedResponse.headers.set("Cache-Control", `max-age=${ttlInSeconds}`);
|
||||
clonedResponse.headers.set("Expires", new Date(Date.now() + ttlInSeconds * 1000).toUTCString());
|
||||
return clonedResponse;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,23 @@ import { responseJSON, responseXML, withExpiry } from "../../../lib/utils.ts";
|
|||
|
||||
const FEED_CACHE_KEY = "feeds-cache";
|
||||
|
||||
// Deno's cache API does not respect these headers.
|
||||
// Until it does, manual expiry handling is needed.
|
||||
// When it's working, this function would not be needed.
|
||||
// See: https://github.com/denoland/deno/issues/25795
|
||||
function isExpired(headers: Headers) {
|
||||
const expiresHeader = headers.get("Expires");
|
||||
if (!expiresHeader) {
|
||||
console.log("No Expires header found, treating as expired");
|
||||
return true;
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
const expiryDate = new Date(expiresHeader);
|
||||
const expired = now > expiryDate;
|
||||
return expired;
|
||||
}
|
||||
|
||||
export const handler = async (
|
||||
request: Request,
|
||||
ctx: FreshContext,
|
||||
|
|
@ -13,11 +30,13 @@ export const handler = async (
|
|||
|
||||
const cache = await caches.open(FEED_CACHE_KEY);
|
||||
const cachedResponse = await cache.match(request);
|
||||
if (cachedResponse) {
|
||||
|
||||
if (cachedResponse && !isExpired(cachedResponse.headers)) {
|
||||
console.log(`Cache hit for feed ${seriesId}`);
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
console.log(`Fetching feed for ${seriesId}`);
|
||||
const series = await caching.getSeries({ id: seriesId });
|
||||
if (!series) {
|
||||
return responseJSON({ message: "Series not found" }, STATUS_CODE.NotFound);
|
||||
|
|
@ -28,7 +47,7 @@ export const handler = async (
|
|||
const response = withExpiry(
|
||||
responseXML(feed, STATUS_CODE.OK),
|
||||
// 2 hours
|
||||
60 * 60 * 2,
|
||||
2 * 60 * 60,
|
||||
);
|
||||
|
||||
await cache.put(request, response.clone());
|
||||
|
|
|
|||
Loading…
Reference in New Issue