games: automatic CS2 / PUBG / R6 match history — games.matches, match_players, seasons, snapshots, accounts; in-app poller (Leetify, FACEIT, Steam share codes, PUBG API, Ubisoft) every 20 min plus scripts/games-ingest.ts for backfills; match history, stats, maps and seasons on the per-game pages
All checks were successful
Deploy production / deploy (push) Successful in 1m6s
All checks were successful
Deploy production / deploy (push) Successful in 1m6s
This commit is contained in:
39
src/lib/games-ingest/http.ts
Normal file
39
src/lib/games-ingest/http.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { SourceError, sleep } from './types';
|
||||
|
||||
const UA = 'stanrunge.dev games tracker (personal, self-hosted)';
|
||||
|
||||
/** GET/POST JSON with a timeout, retrying 429/5xx a few times (honouring Retry-After). */
|
||||
export async function fetchJson<T = unknown>(
|
||||
url: string,
|
||||
init: RequestInit & { retries?: number; allow?: number[] } = {}
|
||||
): Promise<{ status: number; body: T }> {
|
||||
const { retries = 3, allow = [], ...rest } = init;
|
||||
for (let attempt = 0; ; attempt++) {
|
||||
const res = await fetch(url, {
|
||||
...rest,
|
||||
headers: { 'User-Agent': UA, Accept: 'application/json', ...(rest.headers ?? {}) },
|
||||
signal: AbortSignal.timeout(30_000)
|
||||
});
|
||||
if ((res.status === 429 || res.status >= 500) && attempt < retries) {
|
||||
const after = Number(res.headers.get('retry-after'));
|
||||
await sleep(
|
||||
Math.min(90, Number.isFinite(after) && after > 0 ? after : 5 * 2 ** attempt) * 1000
|
||||
);
|
||||
continue;
|
||||
}
|
||||
const text = await res.text();
|
||||
if (!res.ok && !allow.includes(res.status)) {
|
||||
throw new SourceError(
|
||||
`${res.status} from ${new URL(url).host}${new URL(url).pathname}: ${text.slice(0, 160)}`,
|
||||
res.status
|
||||
);
|
||||
}
|
||||
let body: unknown;
|
||||
try {
|
||||
body = text ? JSON.parse(text) : null;
|
||||
} catch {
|
||||
body = text;
|
||||
}
|
||||
return { status: res.status, body: body as T };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user