Retry invoice fetches when Northwind returns a 5xx, with backoff
billing/fetch-invoice.ts
+0−0
import type { Invoice } from "./types";
const API = "https://api.northwind.dev/v2";
export async function fetchInvoice(id: string): Promise<Invoice> {
const res = await fetch(`${API}/invoices/${id}`);
if (!res.ok) {
throw new Error("Request failed");
}
return res.json();
}
export function formatTotal(invoice: Invoice) {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: invoice.currency,
}).format(invoice.total / 100);
}1import type { Invoice } from "./types";
import { retry } from "@/lib/retry";
2
3const API = "https://api.northwind.dev/v2";
4
/** Retries 5xx responses up to 3 times, backing off from 250ms. */
5export async function fetchInvoice(id: string): Promise<Invoice> {
6 const res = await fetch(`${API}/invoices/${id}`); const res = await fetch(`${API}/invoices/${id}`);
7 if (!res.ok) { if (!res.ok) {
8 throw new Error("Request failed"); throw new Error("Request failed");
9 } }
10 return res.json(); return res.json();
return retry(
async () => {
const res = await fetch(`${API}/invoices/${id}`);
if (res.status >= 500) throw new Error(`Northwind ${res.status}`);
if (!res.ok) throw new Error(`Invoice ${id} not found`);
return res.json();
},
{ attempts: 3, backoff: (n) => 250 * 2 ** n },
);
11}
12
13export function formatTotal(invoice: Invoice) {
14 return new Intl.NumberFormat("en-US", {
15 style: "currency",
16 currency: invoice.currency,
17 }).format(invoice.total / 100);
18}