fix(admin): eliminate GoTrue empty-body 500s under bulk load (retry-all + undici keep-alive + sequential bulk), CSV formula-injection guard
This commit is contained in:
+16
-6
@@ -15,11 +15,20 @@
|
||||
* surface as proper 4xx/5xx responses upstream.
|
||||
*/
|
||||
|
||||
// Up to 3 attempts total (1 initial + 2 retries). Delays are applied BEFORE the
|
||||
// 2nd and 3rd attempts respectively, so worst-case added latency is ~350ms —
|
||||
// kept well under a second to keep the admin surface snappy.
|
||||
const MAX_ATTEMPTS = 3;
|
||||
const RETRY_DELAYS_MS = [100, 250];
|
||||
// Up to 5 attempts total (1 initial + 4 retries). Delays are applied BEFORE
|
||||
// attempts 2..5 respectively and are jittered (see `jitter`), so worst-case
|
||||
// added latency is ~80+150+300+600 ≈ 1.13s plus jitter — kept under ~1.5s to
|
||||
// keep the admin surface snappy while reliably riding out the empty-body /
|
||||
// poisoned-keep-alive window that Node 24's bundled undici amplifies.
|
||||
const MAX_ATTEMPTS = 5;
|
||||
const RETRY_DELAYS_MS = [80, 150, 300, 600];
|
||||
|
||||
/** Apply ±30% random jitter so concurrent retries don't synchronise. */
|
||||
function jitter(ms: number): number {
|
||||
if (ms <= 0) return 0;
|
||||
const delta = ms * 0.3;
|
||||
return Math.round(ms - delta + Math.random() * 2 * delta);
|
||||
}
|
||||
|
||||
/** Loose shape that both `AuthError` and `PostgrestError` satisfy. */
|
||||
type MaybeError =
|
||||
@@ -116,7 +125,8 @@ export async function withAdminRetry<R extends { error: MaybeError }>(
|
||||
}
|
||||
|
||||
if (attempt < attempts) {
|
||||
const delay = delays[attempt - 1] ?? delays[delays.length - 1] ?? 0;
|
||||
const base = delays[attempt - 1] ?? delays[delays.length - 1] ?? 0;
|
||||
const delay = jitter(base);
|
||||
if (delay > 0) await sleep(delay);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user