Skip to content

Commit

Permalink
feat: add invalidate endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
kane50613 committed Dec 3, 2024
1 parent 7101350 commit a9e5c82
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 4 deletions.
2 changes: 2 additions & 0 deletions action.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ RUN bun install --frozen-lockfile --production

FROM base AS runner

WORKDIR /app

# Install curl for healthcheck
RUN apk update && apk add curl --no-cache

Expand Down
Binary file modified bun.lockb
Binary file not shown.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"typescript": "^5.7.2"
},
"dependencies": {
"xxhash-wasm": "^1.1.0"
"xxhash-wasm": "^1.1.0",
"zod": "^3.23.8"
}
}
24 changes: 22 additions & 2 deletions src/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ const setCachedQuery = db.prepare<
VALUES ($key, $body, $status, $contentType, strftime('%s', 'now'))
`);

const deleteCachedQuery = db.prepare<undefined, CachedResponse["key"]>(
`DELETE FROM cache WHERE key = ?`
);

export function getCachedResponse(cacheKey: bigint) {
return getCachedQuery.get(cacheKey);
}
Expand All @@ -50,12 +54,24 @@ export function setCachedResponse(
return setCachedQuery.run(cachedResponse);
}

export function createCacheKey(request: Request) {
export function createCacheKey(params: {
method: string;
url: string;
authorization?: string;
}) {
return hasher.h64(
`${request.method} ${request.url} ${request.headers.get("Authorization")}`
`${params.method}:${params.url}:${params.authorization ?? ""}`
);
}

export function createCacheKeyFromRequest(request: Request) {
return createCacheKey({
method: request.method,
url: request.url,
authorization: request.headers.get("Authorization") ?? undefined,
});
}

export function createResponseFromCached(
cached: Omit<CachedResponse, "timestamp" | "key">
) {
Expand All @@ -66,3 +82,7 @@ export function createResponseFromCached(
status: cached.status,
});
}

export function invalidateCache(cacheKey: bigint) {
return deleteCachedQuery.run(cacheKey);
}
5 changes: 5 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { handleApiRequest } from "./routes/api";
import { handleInvalidateRequest } from "./routes/invalidate";

const server = Bun.serve({
fetch(request) {
Expand All @@ -8,6 +9,10 @@ const server = Bun.serve({
return handleApiRequest(request, url);
}

if (url.pathname === "/invalidate" && request.method === "POST") {
return handleInvalidateRequest(request);
}

return new Response("Not found", { status: 404 });
},
});
Expand Down
3 changes: 2 additions & 1 deletion src/routes/api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
createCacheKey,
createCacheKeyFromRequest,
createResponseFromCached,
getCachedResponse,
setCachedResponse,
Expand All @@ -18,7 +19,7 @@ export async function handleApiRequest(request: Request, url: URL) {
return fetchFromRequest(url, request);
}

const cacheKey = createCacheKey(request);
const cacheKey = createCacheKeyFromRequest(request);

const existingCache = getCachedResponse(cacheKey);

Expand Down
20 changes: 20 additions & 0 deletions src/routes/invalidate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { z } from "zod";
import { createCacheKey, invalidateCache } from "../cache";

const schema = z.object({
method: z.string(),
url: z.string(),
authorization: z.string().optional(),
});

export async function handleInvalidateRequest(request: Request) {
const body = schema.parse(await request.json());

const cacheKey = createCacheKey(body);

invalidateCache(cacheKey);

return new Response(null, {
status: 204,
});
}

0 comments on commit a9e5c82

Please sign in to comment.