flushAcks acks entries one at a time (Receive.ts → ackOne → DeliveryPort.ack), and WalletApiDeliveryPort.ack calls client.claim([deliveryId], …) with a single-element array — even though client.claim(entryIds: string[], intoInventory) takes a batch (impl/wallet-api-v2/client.ts:322).
So a 54-token receive makes 54 sequential claim round trips. Measured in the browser: ~180 ms each, ~9.5 s of the receive, and it is the dominant remaining cost now that the mirror-refresh cadence is fixed.
Why this is not just a loop rewrite. ackOne has per-entry recovery: a lineage CONFLICT on claim is caught and converted to reject('other') plus an attention event (Receive.ts:299-305), because a conflict is stale by construction and would otherwise re-process forever. claim() already returns failed[] per entry, so the information is there — but the batch path has to:
- apply the conflict→reject fallback per failed entry, not abandon the batch;
- advance the mailbox cursor only to the last consecutive success, since the cursor means "everything before this is done";
- keep
store() before the claimed ack (the §5.7 ordering the file header calls money-load-bearing).
Expected win: ~9.5 s → well under 1 s for a 54-token receive.
Worth pairing with a test that fails if the cursor advances past a failed entry, and one that fails if a conflicting entry in the middle of a batch stops the rest from being acked.
flushAcksacks entries one at a time (Receive.ts→ackOne→DeliveryPort.ack), andWalletApiDeliveryPort.ackcallsclient.claim([deliveryId], …)with a single-element array — even thoughclient.claim(entryIds: string[], intoInventory)takes a batch (impl/wallet-api-v2/client.ts:322).So a 54-token receive makes 54 sequential claim round trips. Measured in the browser: ~180 ms each, ~9.5 s of the receive, and it is the dominant remaining cost now that the mirror-refresh cadence is fixed.
Why this is not just a loop rewrite.
ackOnehas per-entry recovery: a lineage CONFLICT on claim is caught and converted toreject('other')plus an attention event (Receive.ts:299-305), because a conflict is stale by construction and would otherwise re-process forever.claim()already returnsfailed[]per entry, so the information is there — but the batch path has to:store()before the claimed ack (the §5.7 ordering the file header calls money-load-bearing).Expected win: ~9.5 s → well under 1 s for a 54-token receive.
Worth pairing with a test that fails if the cursor advances past a failed entry, and one that fails if a conflicting entry in the middle of a batch stops the rest from being acked.