Skip to content

fix: OOM prevention with dynamic memory guard#65

Merged
EVWorth merged 5 commits into
mainfrom
fix/oom-large-tables
May 13, 2026
Merged

fix: OOM prevention with dynamic memory guard#65
EVWorth merged 5 commits into
mainfrom
fix/oom-large-tables

Conversation

@EVWorth
Copy link
Copy Markdown
Owner

@EVWorth EVWorth commented May 8, 2026

Summary

Replaces hardcoded 50k row limit with a dynamic memory guard that monitors system-wide available memory.

Changes

  1. MemoryGuard (executor.rs)

    • Stores sysinfo::System as a struct field; calls refresh_memory() on each check instead of creating a new System per invocation
    • Threshold: absolute 512 MB available (was: 95% usage %). Absolute MB is meaningful and machine-independent; a % threshold is meaningless at e.g. 2 GB RAM vs 128 GB RAM
    • check(&mut self) sets self.triggered = true internally — removed separate set_triggered() method and eliminated the redundant two-liner at the call site
    • Fixed doc comment: says "process memory" but measures system memory
  2. Deduplication (executor.rs)

    • Extracted build_select_result() helper shared by the normal Either::Left path and the OOM mid-stream recovery block
    • OOM recovery block was ~50 lines of copy-pasted column/row extraction; now 5 lines
  3. Frontend (ResultsGrid.tsx)

    • Reverted shouldVirtualize threshold from 100 → 500 rows (change had no justification)
    • Removed duplicate OOM warning string from the warnings array; rows_truncated: true already shows the truncation banner — two banners for the same event was confusing

Testing

  • Frontend: 275 tests passing ✅
  • Rust clippy: No warnings ✅
  • Rust build: Clean ✅

EVWorth and others added 4 commits May 2, 2026 18:34
- Always apply LIMIT to SELECT/SHOW/DESCRIBE/EXPLAIN (was conditional)
- Hard cap at 50,000 rows regardless of user settings
- Fix rows_truncated detection to compare against capped_limit
- Lower frontend virtualization threshold from 500 to 100 rows
- Add truncation warning banner when results are capped

Closes #25

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove hardcoded 50k row cap
- Add sysinfo crate for process memory monitoring
- MemoryGuard checks RSS every 1000 rows during fetch
- Triggers when process hits 75% of system RAM
- Gracefully stops fetch and returns accumulated rows with warning
- Add OutOfMemory error variant to CoreError
- Update frontend to show backend warnings
- Truncation banner no longer mentions arbitrary 50k number
- Collapse nested if into single condition (clippy::collapsible_if)
- Use is_multiple_of(1000) instead of % 1000 == 0 (clippy::manual_is_multiple_of)
- Run cargo fmt for consistent formatting
- Changed MemoryGuard to monitor available system memory, not total
- Trigger threshold: 95% of available memory consumed (5% buffer)
- Previous logic used 75% of total memory which could allow crashes when other processes consumed RAM
- New logic prevents runaway queries when system memory is critically low
- Removed per-process RSS tracking; now monitors system-wide availability

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EVWorth EVWorth force-pushed the fix/oom-large-tables branch from 07b1f1f to 834ae0e Compare May 13, 2026 01:12
@EVWorth EVWorth merged commit 14d206b into main May 13, 2026
2 of 4 checks passed
@EVWorth EVWorth deleted the fix/oom-large-tables branch May 13, 2026 01:38
@codecov-commenter
Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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.

2 participants