feat: add auto-retry (3 attempts) for file uploads on flaky connections
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -166,7 +166,10 @@ export function RequirementUploadSlot({
|
|||||||
requirementId: requirement.id,
|
requirementId: requirement.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Upload file with progress tracking
|
// Upload file with progress tracking and auto-retry
|
||||||
|
const maxRetries = 3
|
||||||
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||||
|
try {
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
const xhr = new XMLHttpRequest()
|
const xhr = new XMLHttpRequest()
|
||||||
xhr.upload.addEventListener('progress', (event) => {
|
xhr.upload.addEventListener('progress', (event) => {
|
||||||
@@ -181,11 +184,28 @@ export function RequirementUploadSlot({
|
|||||||
reject(new Error(`Upload failed with status ${xhr.status}`))
|
reject(new Error(`Upload failed with status ${xhr.status}`))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
xhr.addEventListener('error', () => reject(new Error('Upload failed')))
|
xhr.addEventListener('error', () =>
|
||||||
|
reject(new Error('Network error during upload'))
|
||||||
|
)
|
||||||
|
xhr.addEventListener('abort', () =>
|
||||||
|
reject(new Error('Upload was aborted'))
|
||||||
|
)
|
||||||
xhr.open('PUT', url)
|
xhr.open('PUT', url)
|
||||||
xhr.setRequestHeader('Content-Type', file.type)
|
xhr.setRequestHeader('Content-Type', file.type)
|
||||||
xhr.send(file)
|
xhr.send(file)
|
||||||
})
|
})
|
||||||
|
break // Success — exit retry loop
|
||||||
|
} catch (uploadErr) {
|
||||||
|
if (attempt < maxRetries) {
|
||||||
|
const delay = attempt * 2000
|
||||||
|
toast.info(`Upload interrupted, retrying... (${attempt}/${maxRetries})`)
|
||||||
|
setProgress(0)
|
||||||
|
await new Promise((r) => setTimeout(r, delay))
|
||||||
|
} else {
|
||||||
|
throw uploadErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Save metadata
|
// Save metadata
|
||||||
await saveFileMetadata.mutateAsync({
|
await saveFileMetadata.mutateAsync({
|
||||||
|
|||||||
Reference in New Issue
Block a user