fix: retry 429 avec backoff + sérialisation uploadAll + 409 traité comme skipped
This commit is contained in:
@@ -249,8 +249,13 @@ export function useImages() {
|
||||
[items, update],
|
||||
)
|
||||
|
||||
const uploadAll = useCallback(() => {
|
||||
items.filter((i) => i.status === 'ready').forEach((i) => uploadOne(i.id))
|
||||
const uploadAll = useCallback(async () => {
|
||||
const ready = items.filter((i) => i.status === 'ready')
|
||||
for (const item of ready) {
|
||||
await uploadOne(item.id)
|
||||
// Pause de 500ms entre chaque upload pour éviter le rate limit Shopify
|
||||
await new Promise(r => setTimeout(r, 500))
|
||||
}
|
||||
}, [items, uploadOne])
|
||||
|
||||
const removeItem = useCallback((id: string) => {
|
||||
|
||||
@@ -118,12 +118,30 @@ export async function uploadProductImage(
|
||||
const existingUrl = await productImageExists(shopifyProductId, filename)
|
||||
if (existingUrl) return { url: existingUrl, skipped: true }
|
||||
|
||||
// Retry avec backoff exponentiel (gère le 429 rate limit)
|
||||
const MAX_RETRIES = 4
|
||||
let delay = 1000
|
||||
|
||||
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
||||
const res = await fetch(`${baseUrl}/products/${shopifyProductId}/images.json`, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify({ image: { attachment: imageBase64, filename } }),
|
||||
})
|
||||
|
||||
// 409 Conflict = image déjà présente → traiter comme skipped
|
||||
if (res.status === 409) {
|
||||
return { url: `https://placeholder/already-exists/${filename}`, skipped: true }
|
||||
}
|
||||
|
||||
// 429 Too Many Requests → attendre et réessayer
|
||||
if (res.status === 429 && attempt < MAX_RETRIES) {
|
||||
const retryAfter = parseInt(res.headers.get('Retry-After') ?? '0', 10)
|
||||
await new Promise(r => setTimeout(r, retryAfter > 0 ? retryAfter * 1000 : delay))
|
||||
delay *= 2
|
||||
continue
|
||||
}
|
||||
|
||||
if (!res.ok) {
|
||||
const body = await res.text()
|
||||
throw new Error(`Shopify upload error: ${res.status} — ${body}`)
|
||||
@@ -135,3 +153,6 @@ export async function uploadProductImage(
|
||||
}
|
||||
return { url: data.image.src as string }
|
||||
}
|
||||
|
||||
throw new Error('Shopify upload error: trop de tentatives (rate limit persistant)')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user