fix: add rate limiting with retry on 429 in sync-stock

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-26 11:59:37 +02:00
parent d276f6224c
commit 401b43cc04
+21 -11
View File
@@ -80,19 +80,28 @@ export async function POST(req: NextRequest) {
let updated = 0 let updated = 0
let errors = 0 let errors = 0
const sleep = (ms: number) => new Promise(r => setTimeout(r, ms))
const shopifyFetch = async (url: string, opts: RequestInit, retries = 3): Promise<Response> => {
const res = await fetch(url, opts)
if (res.status === 429 && retries > 0) {
const retryAfter = parseInt(res.headers.get('Retry-After') ?? '2', 10)
await sleep(retryAfter * 1000)
return shopifyFetch(url, opts, retries - 1)
}
return res
}
for (let i = 0; i < entries.length; i++) { for (let i = 0; i < entries.length; i++) {
const { shopifyId, stock, title } = entries[i] const { shopifyId, stock, title } = entries[i]
send({ type: 'progress', current: i + 1, total: entries.length, title }) send({ type: 'progress', current: i + 1, total: entries.length, title })
try { try {
// Récupérer le variant pour obtenir inventory_item_id await sleep(300) // éviter le rate limiting (2 req/s max)
const pRes = await fetch(`${baseUrl}/products/${shopifyId}.json?fields=variants`, { headers })
if (pRes.status === 404) { const pRes = await shopifyFetch(`${baseUrl}/products/${shopifyId}.json?fields=variants`, { headers })
// Produit supprimé de Shopify, on ignore silencieusement if (pRes.status === 404) continue
continue
}
if (!pRes.ok) { if (!pRes.ok) {
const msg = `Produit ${shopifyId} erreur (${pRes.status})` send({ type: 'error', title, message: `Produit ${shopifyId} erreur (${pRes.status})` })
send({ type: 'error', title, message: msg })
errors++ errors++
continue continue
} }
@@ -100,13 +109,14 @@ export async function POST(req: NextRequest) {
const inventoryItemId = pData.product.variants[0]?.inventory_item_id const inventoryItemId = pData.product.variants[0]?.inventory_item_id
if (!inventoryItemId) { errors++; continue } if (!inventoryItemId) { errors++; continue }
// Connect (idempotent) await sleep(300)
await fetch(`${baseUrl}/inventory_levels/connect.json`, { await shopifyFetch(`${baseUrl}/inventory_levels/connect.json`, {
method: 'POST', headers, method: 'POST', headers,
body: JSON.stringify({ location_id: locationId, inventory_item_id: inventoryItemId }), body: JSON.stringify({ location_id: locationId, inventory_item_id: inventoryItemId }),
}) })
const setRes = await fetch(`${baseUrl}/inventory_levels/set.json`, { await sleep(300)
const setRes = await shopifyFetch(`${baseUrl}/inventory_levels/set.json`, {
method: 'POST', headers, method: 'POST', headers,
body: JSON.stringify({ location_id: locationId, inventory_item_id: inventoryItemId, available: stock }), body: JSON.stringify({ location_id: locationId, inventory_item_id: inventoryItemId, available: stock }),
}) })