Skip to content
File

Blob: src/worker/queues/blob-gc.ts

typescript52 lines
1import type { QueueHandleResult } from "@/worker/queues/types";
2 
3export interface BlobGcMessage {
4 type: "r2_blob_gc";
5 subject_id: string;
6 storage_id: string;
7 blob_id: string;
8 blob_key: string;
9 not_before_ms: number;
10}
11 
12export function blobGcMessage(input: {
13 subjectId: string;
14 storageId: string;
15 blobId: string;
16 blobKey: string;
17 notBeforeMs: number;
18}): BlobGcMessage {
19 return {
20 type: "r2_blob_gc",
21 subject_id: input.subjectId,
22 storage_id: input.storageId,
23 blob_id: input.blobId,
24 blob_key: input.blobKey,
25 not_before_ms: input.notBeforeMs,
26 };
27}
28 
29export function isBlobGcMessage(value: unknown): value is BlobGcMessage {
30 if (!value || typeof value !== "object") return false;
31 const record = value as Record<string, unknown>;
32 return (
33 record.type === "r2_blob_gc" &&
34 typeof record.subject_id === "string" &&
35 record.subject_id.length > 0 &&
36 typeof record.storage_id === "string" &&
37 record.storage_id.length > 0 &&
38 typeof record.blob_id === "string" &&
39 record.blob_id.length > 0 &&
40 typeof record.blob_key === "string" &&
41 record.blob_key.length > 0 &&
42 typeof record.not_before_ms === "number" &&
43 Number.isFinite(record.not_before_ms)
44 );
45}
46 
47export function retryUntilReady(message: BlobGcMessage, nowMs: number): QueueHandleResult | null {
48 if (message.not_before_ms <= nowMs) return null;
49 const delaySeconds = Math.max(1, Math.min(900, Math.ceil((message.not_before_ms - nowMs) / 1000)));
50 return { action: "retry", delaySeconds };
51}