Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | 15x 15x 13x 13x 11x 11x 9x 9x 7x 7x 7x 6x 6x 4x 6x 4x 4x 3x 3x | // Session caching layer for Better Auth sessions
// Reduces 2 D1 queries per protected request to 0 on cache hit
import type { DualCache } from "./cache";
import { CACHE_TTL } from "./cache";
import type { Auth } from "./auth";
type SessionResult = Awaited<ReturnType<Auth["api"]["getSession"]>>;
// Extract session token from Better Auth's cookie header
function extractSessionToken(headers: Headers): string | null {
const cookie = headers.get("cookie");
if (!cookie) return null;
const match = cookie.match(/better-auth\.session_token=([^;]+)/);
return match?.[1] ?? null;
}
/**
* Get session from cache or fetch from Better Auth.
* On cache hit: 0 D1 queries. On miss: 2 D1 queries (session + user lookup).
*/
export async function getCachedSession(
cache: DualCache,
auth: Auth,
headers: Headers,
): Promise<SessionResult> {
const token = extractSessionToken(headers);
if (!token) return null;
// Check blocklist first (invalidated sessions)
const isBlocked = await cache.get<boolean>(`deleted-session:${token}`);
if (isBlocked) return null;
// Check cache
const cacheKey = `session:${token}`;
const cached = await cache.get<NonNullable<SessionResult>>(cacheKey);
if (cached) return cached;
// Cache miss - fetch from Better Auth (hits D1)
const session = await auth.api.getSession({ headers });
if (session) {
await cache.put(cacheKey, session, {
l1Ttl: CACHE_TTL.SESSION_L1,
l2Ttl: CACHE_TTL.SESSION_L2,
});
}
return session;
}
/**
* Invalidate a session from cache and add to blocklist.
* Called on logout to prevent stale cache from serving revoked sessions.
*/
export async function invalidateSession(
cache: DualCache,
headers: Headers,
): Promise<void> {
const token = extractSessionToken(headers);
if (!token) return;
// Delete cached session
await cache.delete(`session:${token}`);
// Add to blocklist so stale KV entries are rejected
await cache.put(`deleted-session:${token}`, true, {
l1Ttl: CACHE_TTL.SESSION_L1,
l2Ttl: CACHE_TTL.SESSION_L2,
});
}
|