import { env } from "cloudflare:workers";
import { batch, first, run, stmt } from "../db";
import { randomId } from "../crypto";
import { CAPS, enforceRateLimit, numberVar } from "../limits";
import { HttpError } from "../errors";
import type { JobTokenAccess } from "./job-token";
const DEFAULT_CACHE_BYTES_PER_REPO = 2 * 1024 * 1024 * 1024;
const MAX_ENTRY_BYTES = 1024 * 1024 * 1024;
const MAX_KEY_LENGTH = 512;
const MAX_RESTORE_KEYS = 10;
const EVICTION_BATCH = 100;
const IDLE_EVICTION_MS = 7 * 24 * 60 * 60 * 1000;
const VERSION = /^[0-9a-f]{1,64}$/;
type CacheRow = {
id: string;
repo_id: string;
ref: string;
key: string;
version: string;
size: number;
r2_key: string;
created_at: number;
last_used_at: number;
};
type CacheScope = { repoId: string; ref: string; defaultRef: string };
export function cacheQuotaBytes(): number {
return numberVar(env.CACHE_BYTES_PER_REPO, DEFAULT_CACHE_BYTES_PER_REPO);
}
function json(data: unknown, status: number): Response {
return Response.json(data, { status });
}
async function scopeFor(access: JobTokenAccess): Promise<CacheScope | null> {
const row = await first<{ ref: string; default_branch: string }>(
`SELECT w.ref, r.default_branch FROM workflow_jobs j JOIN workflow_runs w ON w.id = j.run_id