This document describes the implementation of graceful partial batch failure handling in the auto-release worker. The worker now processes each escrow independently and continues processing even when individual escrows fail.
Previously, the auto-release worker processed escrows in batches but lacked comprehensive tracking and reporting for partial failures. While it did continue processing after failures, it didn't:
- Track success/failure counts
- Provide detailed batch processing summaries
- Log comprehensive failure information
- Have adequate test coverage for partial failure scenarios
File: src/workers/auto-release.worker.ts
-
Independent Processing: Each escrow is processed within its own try-catch block, ensuring failures don't affect other escrows in the batch.
-
Success/Failure Tracking:
successCount: Tracks successfully processed escrowsfailureCount: Tracks failed escrowsfailures: Array storing detailed failure information (escrowId + error message)
-
Enhanced Logging:
- Batch start log:
Processing batch of N eligible escrow(s) for auto-release - Individual success log:
Auto-release succeeded for escrow {id} (tx: {hash}) - Individual failure log:
Auto-release failed for escrow {id}: {error} - Batch summary log:
Batch complete: X succeeded, Y failed out of Z total - Failed escrows list:
Failed escrows: escrow-1 (error), escrow-2 (error)...
- Batch start log:
-
Skip Reasons Logging: Added debug logs for skipped escrows (disputes, already completed)
async run(referenceTime = new Date()): Promise<void> {
const eligible = await this.escrowRepository.findAutoReleaseEligible(referenceTime);
if (eligible.length === 0) {
return;
}
let successCount = 0;
let failureCount = 0;
const failures: Array<{ escrowId: string; error: string }> = [];
this.logger.log(`Processing batch of ${eligible.length} eligible escrow(s)...`);
for (const escrow of eligible) {
try {
// Process escrow (with dispute/completion checks)
// On success: increment successCount, log success
} catch (error) {
// On failure: increment failureCount, store failure details, log error
failureCount++;
failures.push({ escrowId: escrow.id, error: errorMessage });
this.logger.error(`Auto-release failed for escrow ${escrow.id}...`);
}
}
// Log batch summary
this.logger.log(`Batch complete: ${successCount} succeeded, ${failureCount} failed...`);
if (failures.length > 0) {
this.logger.warn(`Failed escrows: ${failures.map(...)}`);
}
}File: src/workers/auto-release.worker.spec.ts
Added comprehensive test suite: "Partial batch failure recovery"
-
continues processing remaining escrows when one fails
- 3 escrows: success, fail, success
- Verifies all 3 are attempted
- Confirms only successful ones are marked complete
-
logs individual failure details without aborting the batch
- 2 escrows: fail, success
- Verifies error logs contain failure details
- Confirms batch summary logs are present
-
tracks successful and failed counts separately
- 4 escrows: success, fail, fail, success
- Verifies summary shows "2 succeeded, 2 failed out of 4 total"
- Confirms failed escrows list in warning log
-
handles all escrows failing gracefully
- 2 escrows: fail, fail
- Verifies all are attempted
- Confirms summary shows "0 succeeded, 2 failed out of 2 total"
-
handles all escrows succeeding
- 2 escrows: success, success
- Verifies all succeed
- Confirms no warning logs are generated
File: test/integration/auto-release-batch.integration-spec.ts
New integration test suite with real database interactions.
-
processes all escrows independently when middle escrow fails
- Creates 3 escrows in database
- Pattern: success, fail, success
- Verifies database states after processing
-
handles multiple failures in a batch without aborting
- Creates 4 escrows
- Pattern: success, fail, fail, success
- Validates all database states
-
continues processing after first escrow fails
- 2 escrows: fail, success
- Ensures first failure doesn't prevent second from processing
-
handles all escrows failing without corruption
- Creates 3 escrows, all fail
- Verifies all remain in SHIPPED state with no tx hash
-
logs detailed failure information for each failed escrow
- Verifies batch logs, error logs, and summary logs
- Checks for warning logs with failure list
-
processes successfully after retrying failed escrows
- First run: escrow fails
- Second run: same escrow succeeds
- Demonstrates retry capability
✅ Process each escrow independently in the batch
- Each escrow is wrapped in its own try-catch block
- Failures are isolated and don't affect other escrows
✅ If one escrow fails, continue processing the rest
- Loop continues after catching errors
- All eligible escrows are attempted
✅ Log individual failure details without aborting the batch
- Individual error logs with escrow ID and error message
- Stack traces preserved for debugging
- Failed escrows list in warning log
✅ Track successful and failed counts separately
successCountandfailureCountvariables- Summary log shows both counts
- Failures array stores detailed information
✅ Add unit test for partial batch failure recovery
- 5 comprehensive unit tests added
- Cover various failure patterns
- Test logging behavior
✅ Add integration test for mixed success/failure batch
- 6 integration tests with real database
- Test various failure patterns
- Verify database state consistency
- Reliability: Batch processing is now fault-tolerant
- Observability: Detailed logs for debugging and monitoring
- Accountability: Clear tracking of success/failure rates
- Testability: Comprehensive test coverage for confidence
- Maintainability: Clear code structure with explicit error handling
Once dependencies are installed, run:
# Unit tests
npm test -- auto-release.worker.spec.ts
# Integration tests
npm run test:integration -- auto-release-batch.integration-spec.ts
# All tests
npm testPotential improvements for future iterations:
- Add metrics/monitoring for success/failure rates
- Implement retry logic with exponential backoff
- Add circuit breaker pattern for contract service failures
- Store failure reasons in database for analysis
- Add alerting when failure rate exceeds threshold