@@ -16,6 +16,7 @@ import {
|
||||
DeleteObjectCommand,
|
||||
GetObjectCommand,
|
||||
ListObjectsV2Command,
|
||||
HeadObjectCommand,
|
||||
} from "@aws-sdk/client-s3";
|
||||
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
||||
import fs from "fs";
|
||||
@@ -278,6 +279,30 @@ export async function uploadToHetzner(
|
||||
return { key };
|
||||
}
|
||||
|
||||
/**
|
||||
* In-process cache for Hetzner key existence checks.
|
||||
* Positive hits (key exists) are cached indefinitely for the process lifetime
|
||||
* since uploaded files are immutable UUID-named objects that never disappear.
|
||||
* Negative hits are not cached so newly-migrated files are picked up immediately.
|
||||
*/
|
||||
const hetznerExistsCache = new Map<string, true>();
|
||||
|
||||
/**
|
||||
* Returns true if the given key exists in the Hetzner bucket.
|
||||
* Results are cached in process memory after the first check.
|
||||
*/
|
||||
export async function hetznerKeyExists(key: string): Promise<boolean> {
|
||||
if (hetznerExistsCache.has(key)) return true;
|
||||
try {
|
||||
const { client, bucket } = await buildHetznerClient();
|
||||
await client.send(new HeadObjectCommand({ Bucket: bucket, Key: key }));
|
||||
hetznerExistsCache.set(key, true);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all object keys currently stored in the Hetzner bucket.
|
||||
* Paginates automatically. Used by the migration tool.
|
||||
|
||||
Reference in New Issue
Block a user