fix(api): add retry for document blob head checks
Implement a retry mechanism for document blob HEAD requests to handle S3 read-after-write propagation delays. This prevents 409 errors when the client calls the endpoint immediately after performing a direct upload to S3 via a presigned URL.
This commit is contained in:
parent
596c04d4d3
commit
9931c7d0d8
1 changed files with 32 additions and 12 deletions
|
|
@ -84,19 +84,39 @@ export async function POST(req: NextRequest) {
|
||||||
|
|
||||||
for (const doc of documentsData) {
|
for (const doc of documentsData) {
|
||||||
let headSize = doc.size;
|
let headSize = doc.size;
|
||||||
try {
|
|
||||||
const head = await headDocumentBlob(doc.id, testNamespace);
|
// Retry HEAD check to handle S3 read-after-write propagation delays.
|
||||||
if (head.contentLength > 0) headSize = head.contentLength;
|
// The client uploads bytes directly to S3 via presigned URL, then
|
||||||
} catch (error) {
|
// immediately calls this endpoint. On serverless platforms the HEAD
|
||||||
if (isMissingBlobError(error)) {
|
// request may reach S3 before the PUT is visible.
|
||||||
return NextResponse.json(
|
const HEAD_RETRIES = 3;
|
||||||
{
|
const HEAD_RETRY_DELAY_MS = 500;
|
||||||
error: `Blob missing for document ${doc.id}. Upload bytes first using /api/documents/blob/upload/presign.`,
|
let headError: unknown = null;
|
||||||
},
|
for (let attempt = 0; attempt < HEAD_RETRIES; attempt++) {
|
||||||
{ status: 409 },
|
headError = null;
|
||||||
);
|
try {
|
||||||
|
const head = await headDocumentBlob(doc.id, testNamespace);
|
||||||
|
if (head.contentLength > 0) headSize = head.contentLength;
|
||||||
|
break;
|
||||||
|
} catch (error) {
|
||||||
|
if (isMissingBlobError(error)) {
|
||||||
|
headError = error;
|
||||||
|
if (attempt < HEAD_RETRIES - 1) {
|
||||||
|
await new Promise((r) => setTimeout(r, HEAD_RETRY_DELAY_MS));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw error;
|
}
|
||||||
|
if (headError && isMissingBlobError(headError)) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
error: `Blob missing for document ${doc.id}. Upload bytes first using /api/documents/blob/upload/presign.`,
|
||||||
|
},
|
||||||
|
{ status: 409 },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await db
|
await db
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue