| 1 | /** How big an artifact is, as people read sizes. */ |
| 2 | export function formatBytes(bytes: number): string { |
| 3 | if (bytes < 1024 * 1024) return `${Math.max(1, Math.round(bytes / 1024))} KB`; |
| 4 | if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; |
| 5 | return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`; |
| 6 | } |
| 7 | |
| 8 | /** When an artifact goes, from now: "expires today", "expires in 13 days". */ |
| 9 | export function expiresIn(at: string | null, now: number = Date.now()): string { |
| 10 | if (!at) return ""; |
| 11 | const ms = Date.parse(at) - now; |
| 12 | if (Number.isNaN(ms)) return ""; |
| 13 | if (ms <= 0) return "expired"; |
| 14 | const days = Math.floor(ms / 86_400_000); |
| 15 | if (days === 0) return "expires today"; |
| 16 | if (days === 1) return "expires tomorrow"; |
| 17 | return `expires in ${days} days`; |
| 18 | } |
| 19 | |
| 20 | /** |
| 21 | * Artifacts older runners kept in Workers KV. None has been made there |
| 22 | * since artifacts moved to R2 on 2026-10-08, and KV expires each 14 days |
| 23 | * after it was made: from 2026-10-22T00:00Z every one is gone. Delete the |
| 24 | * KV artifact code (here, artifacts.server.ts, and apps/api/src/blobs.rs) |
| 25 | * after that date. |
| 26 | */ |
| 27 | export const LEGACY_KV_UNTIL = Date.parse("2026-10-22T00:00:00Z"); |
| 28 | /** Runs made from this time on kept their artifacts in R2 only. */ |
| 29 | export const LEGACY_KV_BEFORE = Date.parse("2026-10-09T00:00:00Z"); |
| 30 | |
| 31 | /** |
| 32 | * Whether a run's page asks KV for artifacts an older runner kept there: |
| 33 | * only for a finished run made before the move, and only until they have |
| 34 | * all expired. A KV list is the dearest thing KV does, and a run still |
| 35 | * going refreshes its page every few seconds. |
| 36 | */ |
| 37 | export function legacyArtifactsWorthAsking(run: { createdAt: string; status: string }, now: number = Date.now()): boolean { |
| 38 | return now < LEGACY_KV_UNTIL && run.status === "completed" && Date.parse(run.createdAt) < LEGACY_KV_BEFORE; |
| 39 | } |