fix(debug): use streaming to handle large JSONL files#817
fix(debug): use streaming to handle large JSONL files#817minislively wants to merge 1 commit intoryoppippi:mainfrom
Conversation
The debug module was still using `readFile` + `split('\n')` pattern which can cause
`RangeError: Invalid string length` when processing large JSONL files (>512MB).
This change:
- Exports `processJSONLFileByLine` from data-loader.ts for reuse
- Refactors `detectMismatches` in debug.ts to use streaming
- Ensures consistent memory-safe file processing across the codebase
Fixes memory issues when running debug commands on large usage datasets.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughExposed Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/ccusage/src/debug.ts (1)
137-145: Guard pricing lookup failures to prevent stream abort.
Result.unwrap()will throw on failures (unknown model, pricing fetch errors), which breaks the streaming and skips remaining lines in the file. UseResult.isFailure()with early return, consistent with the error handling pattern already established at lines 116-118 in this same function.🔧 Suggested fix
- const calculatedCost = await Result.unwrap( - fetcher.calculateCostFromTokens(data.message.usage, model), - ); + const costResult = await fetcher.calculateCostFromTokens(data.message.usage, model); + if (Result.isFailure(costResult)) { + return; + } + const calculatedCost = costResult.value;
Summary
The debug module was still using the
readFile+split('\n')pattern which can causeRangeError: Invalid string lengthwhen processing large JSONL files (>512MB).This is a follow-up to PR #706 which fixed the same issue in
data-loader.tsbut missed thedebug.tsmodule.Changes
processJSONLFileByLinefromdata-loader.tsfor reusedetectMismatchesindebug.tsto use streaming instead ofreadFilereadFileimport fromdebug.tsProblem
When users have large usage datasets (1.5GB+ across many files), running debug commands like
ccusage debugwould fail with:Solution
Reuse the existing
processJSONLFileByLinehelper which uses Node.js streams (createReadStream+readline) to process files line-by-line without loading the entire file into memory.Test Plan
processJSONLFileByLineexport doesn't break existing importsSupersedes #815
🤖 Generated with Claude Code
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.