fix(simplefin): retry transient fetch failures (3 attempts, 1s/2s backoff)
This commit is contained in:
parent
a66fe13bc6
commit
7d42d119c0
|
|
@ -83,6 +83,9 @@ async function claimSetupToken(setupToken) {
|
|||
return accessUrl;
|
||||
}
|
||||
|
||||
const FETCH_RETRY_ATTEMPTS = 3;
|
||||
const FETCH_RETRY_DELAYS = [1000, 2000]; // ms between attempts 1→2 and 2→3
|
||||
|
||||
async function fetchAccountsAndTransactions(accessUrl, sinceEpoch) {
|
||||
let url;
|
||||
try {
|
||||
|
|
@ -95,18 +98,34 @@ async function fetchAccountsAndTransactions(accessUrl, sinceEpoch) {
|
|||
const baseUrl = `${url.protocol}//${url.host}${url.pathname.replace(/\/?$/, '')}`;
|
||||
const endpoint = `${baseUrl}/accounts?start-date=${Math.floor(sinceEpoch)}&version=2`;
|
||||
|
||||
let data;
|
||||
let lastErr;
|
||||
for (let attempt = 0; attempt < FETCH_RETRY_ATTEMPTS; attempt++) {
|
||||
if (attempt > 0) await new Promise(r => setTimeout(r, FETCH_RETRY_DELAYS[attempt - 1]));
|
||||
|
||||
let res;
|
||||
try {
|
||||
const res = await fetch(endpoint, {
|
||||
res = await fetch(endpoint, {
|
||||
headers: { 'Authorization': `Basic ${basicAuth}` },
|
||||
signal: AbortSignal.timeout(30000),
|
||||
});
|
||||
} catch (err) {
|
||||
// Network error or timeout — retry unless this was the last attempt
|
||||
if (attempt < FETCH_RETRY_ATTEMPTS - 1) { lastErr = err; continue; }
|
||||
throw sanitizeError(err);
|
||||
}
|
||||
|
||||
if (res.status === 403) {
|
||||
throw Object.assign(new Error('SimpleFIN access has been revoked — please reconnect'), { code: 'SIMPLEFIN_REVOKED' });
|
||||
}
|
||||
if (!res.ok) {
|
||||
throw new Error(`SimpleFIN fetch failed (HTTP ${res.status})`);
|
||||
const err = new Error(`SimpleFIN fetch failed (HTTP ${res.status})`);
|
||||
// Retry transient server errors; surface client errors immediately
|
||||
if (attempt < FETCH_RETRY_ATTEMPTS - 1 && res.status >= 500) { lastErr = err; continue; }
|
||||
throw sanitizeError(err);
|
||||
}
|
||||
|
||||
let data;
|
||||
try {
|
||||
data = await res.json();
|
||||
} catch (err) {
|
||||
throw sanitizeError(err);
|
||||
|
|
@ -119,8 +138,10 @@ async function fetchAccountsAndTransactions(accessUrl, sinceEpoch) {
|
|||
.join('; ');
|
||||
data._errlistSummary = msgs;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
throw sanitizeError(lastErr);
|
||||
}
|
||||
|
||||
function normalizeAccount(rawAccount, dataSourceId, userId) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue