Handle non-JSON BoA backfill errors

Co-authored-by: Adam Moussa <amoussa1229@users.noreply.github.com>
This commit is contained in:
Cursor Agent 2026-05-08 00:09:23 +00:00
parent 71b7645416
commit 21e77d5888
No known key found for this signature in database

View file

@ -140,7 +140,17 @@ async function backfillBoA() {
const transactionId = const transactionId =
headers["transactionid"] || headers["x-transactionid"] || headers["transactionid"] || headers["x-transactionid"] ||
headers["x-correlation-id"] || headers["x-cashpro-transaction-id"] || null; headers["x-correlation-id"] || headers["x-cashpro-transaction-id"] || null;
const data = JSON.parse(text); let data = {};
let parseError = null;
if (text.trim()) {
try {
data = JSON.parse(text);
} catch (err) {
parseError = err;
}
} else {
parseError = new Error("BoA returned an empty response body");
}
await ddb.send(new PutCommand({ await ddb.send(new PutCommand({
TableName: TABLE_NAME, TableName: TABLE_NAME,
@ -153,6 +163,7 @@ async function backfillBoA() {
transaction_id: transactionId, transaction_id: transactionId,
check_numbers: items.map((i) => i.checkNumber), check_numbers: items.map((i) => i.checkNumber),
total_amount: items.reduce((sum, i) => sum + parseFloat(i.amount), 0).toFixed(2), total_amount: items.reduce((sum, i) => sum + parseFloat(i.amount), 0).toFixed(2),
response_headers: JSON.stringify(headers),
response_body: text, response_body: text,
success: res.ok, success: res.ok,
processed_items: data.processedItems || 0, processed_items: data.processedItems || 0,
@ -161,7 +172,11 @@ async function backfillBoA() {
}, },
})); }));
return { ok: res.ok, status: res.status, data }; if (res.ok && parseError) {
throw new Error(`Backfill ${label} failed: BoA returned invalid JSON (HTTP ${res.status})`);
}
return { ok: res.ok, status: res.status, data, text, parseError };
}; };
for (let i = 0; i < toSubmit.length; i += BOA_BATCH_SIZE) { for (let i = 0; i < toSubmit.length; i += BOA_BATCH_SIZE) {
@ -179,14 +194,17 @@ async function backfillBoA() {
// Parse the error to separate duplicates from genuinely new items // Parse the error to separate duplicates from genuinely new items
const dupeCheckNumbers = new Set(); const dupeCheckNumbers = new Set();
for (const item of result.data.issueList || []) { for (const item of result.data?.issueList || []) {
if (ALREADY_SUBMITTED.has(item.status)) { if (ALREADY_SUBMITTED.has(item.status)) {
dupeCheckNumbers.add(item.checkNumber); dupeCheckNumbers.add(item.checkNumber);
} }
} }
if (dupeCheckNumbers.size === 0) { if (dupeCheckNumbers.size === 0) {
throw new Error(`Backfill batch ${batchNum} failed with non-duplicate error: ${result.status}`); const detail = result.parseError
? "BoA returned a non-JSON response"
: "BoA returned a non-duplicate error";
throw new Error(`Backfill batch ${batchNum} failed: ${detail} (HTTP ${result.status})`);
} }
totalSkippedDuplicates += dupeCheckNumbers.size; totalSkippedDuplicates += dupeCheckNumbers.size;
@ -198,7 +216,10 @@ async function backfillBoA() {
const retryResult = await submitBatch(retryItems, `batch ${batchNum} retry`); const retryResult = await submitBatch(retryItems, `batch ${batchNum} retry`);
if (!retryResult.ok) { if (!retryResult.ok) {
console.error(`Backfill batch ${batchNum} retry failed:`, JSON.stringify(retryResult.data)); console.error(`Backfill batch ${batchNum} retry failed:`, JSON.stringify(retryResult.data));
throw new Error(`Backfill batch ${batchNum} retry failed: ${retryResult.status}`); const detail = retryResult.parseError
? "BoA returned a non-JSON response"
: `BoA returned ${JSON.stringify(retryResult.data)}`;
throw new Error(`Backfill batch ${batchNum} retry failed: ${detail} (HTTP ${retryResult.status})`);
} }
totalProcessed += retryResult.data.processedItems; totalProcessed += retryResult.data.processedItems;
console.log(`Backfill batch ${batchNum} retry: ${retryResult.data.processedItems} processed`); console.log(`Backfill batch ${batchNum} retry: ${retryResult.data.processedItems} processed`);