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,26 +166,46 @@ export function RequirementUploadSlot({
|
||||
requirementId: requirement.id,
|
||||
})
|
||||
|
||||
// Upload file with progress tracking
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest()
|
||||
xhr.upload.addEventListener('progress', (event) => {
|
||||
if (event.lengthComputable) {
|
||||
setProgress(Math.round((event.loaded / event.total) * 100))
|
||||
}
|
||||
})
|
||||
xhr.addEventListener('load', () => {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
resolve()
|
||||
// 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) => {
|
||||
const xhr = new XMLHttpRequest()
|
||||
xhr.upload.addEventListener('progress', (event) => {
|
||||
if (event.lengthComputable) {
|
||||
setProgress(Math.round((event.loaded / event.total) * 100))
|
||||
}
|
||||
})
|
||||
xhr.addEventListener('load', () => {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
resolve()
|
||||
} else {
|
||||
reject(new Error(`Upload failed with status ${xhr.status}`))
|
||||
}
|
||||
})
|
||||
xhr.addEventListener('error', () =>
|
||||
reject(new Error('Network error during upload'))
|
||||
)
|
||||
xhr.addEventListener('abort', () =>
|
||||
reject(new Error('Upload was aborted'))
|
||||
)
|
||||
xhr.open('PUT', url)
|
||||
xhr.setRequestHeader('Content-Type', file.type)
|
||||
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 {
|
||||
reject(new Error(`Upload failed with status ${xhr.status}`))
|
||||
throw uploadErr
|
||||
}
|
||||
})
|
||||
xhr.addEventListener('error', () => reject(new Error('Upload failed')))
|
||||
xhr.open('PUT', url)
|
||||
xhr.setRequestHeader('Content-Type', file.type)
|
||||
xhr.send(file)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Save metadata
|
||||
await saveFileMetadata.mutateAsync({
|
||||
|
||||
Reference in New Issue
Block a user