Skip to content

perf(export): stream large exports in bounded chunks instead of buffe… - #1290

Merged
RUKAYAT-CODER merged 1 commit into
rinafcode:mainfrom
shogun444:perf/1179-stream-export-chunks
Aug 30, 2026
Merged

perf(export): stream large exports in bounded chunks instead of buffe…#1290
RUKAYAT-CODER merged 1 commit into
rinafcode:mainfrom
shogun444:perf/1179-stream-export-chunks

Conversation

@shogun444

@shogun444 shogun444 commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Closes #1179


Why This PR Exists

Export serializers in src/lib/export-scheduler/exporter.ts previously built entire export payloads in memory as single monolithic strings before wrapping them into a Blob. Specifically:

  • CSV accumulated via csvLines.join('\n')
  • JSON performed JSON.stringify(data.rows, null, 2) on full datasets
  • XLSX and PDF performed repeated string concatenation across large XML and HTML payloads

On large datasets, this caused heavy memory spikes and $O(n^2)$ string reallocation overhead. This PR introduces bounded chunking primitives and incremental parts assembly to eliminate monolithic string concatenation while maintaining 100% byte-for-byte output parity.


What Changed

  • Streaming & Chunking Primitives (src/lib/export/utils.ts):
    • Added ExportStreamOptions interface supporting configurable chunkSize and per-chunk progress callbacks.
    • Implemented async generators createCSVSnapshot and createJSONSnapshot to yield bounded row batches.
    • Centralized robust serialization escaping helpers: escapeCSVCell, escapeXml, and escapeHtml.
  • Production Exporter Wiring (src/lib/export-scheduler/exporter.ts):
    • Refactored exportToCSV and exportToJSON to consume async generators and build the final Blob from discrete chunks.
    • Refactored exportToXLSX and exportToPDF to assemble from incremental parts arrays rather than repeated string concatenation.
    • Replaced duplicate local escaping routines with shared utilities.
  • Test Coverage & Verification:
    • Added 6 unit tests in src/lib/export/utils.test.ts covering escaping, batch chunking, empty states, progress callbacks, and JSON pretty-print parity.
    • Strengthened src/lib/export-scheduler/__tests__/exporter.test.ts with a FileReader-based readBlobText helper to verify exact content equivalence rather than simple instanceof Blob checks.

Files Changed

File Changes
src/lib/export/utils.ts New/Updated: Added createCSVSnapshot, createJSONSnapshot, ExportStreamOptions, and escaping helpers
src/lib/export-scheduler/exporter.ts Wired async generators into exportToCSV/exportToJSON; converted XLSX/PDF to incremental parts arrays
src/lib/export/utils.test.ts New: 6 unit tests for chunking, escaping, progress events, and empty-state edge cases
src/lib/export-scheduler/__tests__/exporter.test.ts Replaced shallow Blob type checks with full byte-level content verification

Type of Change

  • Performance / Memory optimization (non-breaking change)
  • Refactor / Code modernization
  • Tests

Test Evidence

Local Verification

  • Formatting: prettier --check passes cleanly across all changed files
  • Type Check: npm run type-check passes with 0 errors
  • Linting: npm run lint passes with 0 warnings/errors
  • Unit & Integration Tests: 15/15 tests passing across export test suites
  • Production Build: npm run build compiled successfully (72 static pages generated)
 ✓ src/lib/export/utils.test.ts (6 tests)
   ✓ escapes CSV cells containing commas, quotes, and newlines
   ✓ yields CSV rows in bounded chunk batches with headers
   ✓ handles header-only empty CSV generation
   ✓ invokes progress callback on chunk boundaries
   ✓ produces byte-for-byte identical output to JSON.stringify(rows, null, 2)
   ✓ handles empty JSON datasets gracefully

 ✓ src/lib/export-scheduler/__tests__/exporter.test.ts (9 tests)
   ✓ exports CSV with accurate content matching snapshot
   ✓ exports formatted JSON with identical structure
   ✓ builds XLSX payload from parts array
   ✓ builds PDF payload from parts array

Test Files  2 passed (2)
     Tests  15 passed (15)
     
     

@drips-wave

drips-wave Bot commented Aug 30, 2026

Copy link
Copy Markdown

@shogun444 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@RUKAYAT-CODER

Copy link
Copy Markdown
Contributor

Thank you for contributing to the project.

@RUKAYAT-CODER
RUKAYAT-CODER merged commit 0dba4de into rinafcode:main Aug 30, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stream large exports instead of buffering in memory

2 participants