perf(reconcile): chunked Promise.all in member loop

This commit is contained in:
Jennie Robinson Faber 2026-04-27 11:32:27 +01:00
parent 5432dfe8f2
commit 2611a2a973
2 changed files with 36 additions and 17 deletions

View file

@ -65,37 +65,56 @@ export default defineEventHandler(async (event) => {
let skipped = 0
let memberErrors = 0
for (const member of members) {
async function processMember(member) {
let txs
try {
txs = await listTransactionsWithRetry(member.helcimCustomerId)
} catch (err) {
memberErrors++
console.error(`[reconcile] member=${member._id}: ${err?.message || err}`)
continue
return { error: true }
}
const result = { error: false, txExamined: 0, created: 0, existed: 0, skipped: 0 }
for (const tx of txs) {
txExamined++
result.txExamined++
if (!RECONCILABLE_STATUSES.has(tx?.status)) {
skipped++
result.skipped++
continue
}
if (!apply) {
const existing = await Payment.findOne({ helcimTransactionId: tx.id })
if (existing) existed++
else created++
if (existing) result.existed++
else result.created++
continue
}
// Note: deliberately NOT passing sendConfirmation — cron back-fills must
// not re-send confirmation emails for transactions the member has already
// been notified about (or that pre-date Mongo Payment tracking entirely).
const result = await upsertPaymentFromHelcim(member, tx)
if (result.created) created++
else if (result.payment) existed++
else skipped++
const upsertResult = await upsertPaymentFromHelcim(member, tx)
if (upsertResult.created) result.created++
else if (upsertResult.payment) result.existed++
else result.skipped++
}
return result
}
const CHUNK_SIZE = 8
for (let i = 0; i < members.length; i += CHUNK_SIZE) {
const chunk = members.slice(i, i + CHUNK_SIZE)
const results = await Promise.all(chunk.map((m) => processMember(m)))
for (const r of results) {
if (r.error) {
memberErrors++
continue
}
txExamined += r.txExamined
created += r.created
existed += r.existed
skipped += r.skipped
}
}