fix: prevent concurrent mine corruption, OOM crashes, and Ctrl+C corruption - #130
fix: prevent concurrent mine corruption, OOM crashes, and Ctrl+C corruption#130minimexat wants to merge 2 commits into
Conversation
…uption - Add palace-level lockfile (_acquire_palace_lock / _release_palace_lock) using fcntl (Unix) / msvcrt (Windows) to prevent simultaneous mines from corrupting ChromaDB. Clear error message instead of silent corruption. - Add BATCH_SIZE=50 cap and add_drawers_batch() to prevent bad allocation crashes when mining large files that generate hundreds of chunks. - Add SIGINT handler to mine() for graceful Ctrl+C: finishes current file cleanly before stopping. Already-mined files are skipped on re-run.
travisbreaks
left a comment
There was a problem hiding this comment.
Thanks for tackling these three real problems (concurrent mine corruption, OOM on large files, Ctrl+C corruption). The approach is sound overall. A few items to consider:
1. fcntl import at module top level breaks Windows
import fcntl # line 18 — unconditional importfcntl doesn't exist on Windows. The conditional msvcrt usage inside _acquire_palace_lock() is correct, but the module-level import fcntl will crash on import before it ever gets there. This should be a conditional import:
# At module level:
if sys.platform != "win32":
import fcntlOr move the import inside the function body.
2. Stale lock after crash/SIGKILL
If the process is killed (SIGKILL, power loss, OOM-killer), .mine.lock will be orphaned and all future mine invocations will fail with "Another mine is already running." The error message says "delete .mine.lock if it crashed" which is good guidance, but a stale-lock detection (e.g. write PID to the lock file, check if that PID is alive on next acquire) would prevent users from hitting this in production.
3. Hardcoded BATCH_SIZE = 50
50 is a reasonable default, but the sweet spot depends on document size and available RAM. Consider making this configurable via --batch-size CLI flag or mempalace.yaml config, with 50 as the default.
4. add_drawers_batch silently swallows duplicates
if "already exists" not in str(e).lower():
raiseThis silently skips duplicate entries. That's probably fine for idempotent re-mining, but a logger.debug() here would help users understand why drawer counts don't match expectations.
5. Signal handler scope
signal.signal(signal.SIGINT, _handle_interrupt) is set inside mine(). If mine() is called as a library function (not from CLI), this overwrites the caller's signal handler without restoring it. Consider saving/restoring the original handler in the finally block:
old_handler = signal.signal(signal.SIGINT, _handle_interrupt)
try:
...
finally:
signal.signal(signal.SIGINT, old_handler)
if lock is not None:
_release_palace_lock(lock)6. No tests
CONTRIBUTING.md says "Write code with tests" and "All tests must pass via pytest tests/ -v". The existing test_miner.py has 15 tests, but none cover concurrency or signal handling. Even basic tests would strengthen this:
- Lock acquisition/release lifecycle
- Double-lock returns error
- Batch splitting with >50 items
None of these are blockers for the concept, but items 1 (Windows import crash) and 5 (signal handler leak) are bugs that should be fixed before merge. The rest are improvements worth considering.
Overall solid work addressing real pain points.
…ter mine() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PR Review: fix: prevent concurrent mine corruption, OOM crashes, and Ctrl+C corruptionExecutive Summary
Affected Areas: Business Impact: Prevents silent data corruption and hard crashes during mining — critical for user trust and data integrity. Flow Changes: Ratings
PR Health
High Priority Issues🐛 #1:
|
What
Three crash fixes for stability issues discovered during real-world mining.
Changes
Concurrent mine lock
Running multiple
mempalace mineprocesses simultaneously causes a ChromaDB file locking violation and silent palace corruption. Added palace-level lockfile usingfcntl(Unix) /msvcrt(Windows) with a clear error message instead of silent corruption.OOM batch cap
Large files (JS bundles, SQL dumps) can generate hundreds of chunks submitted in a single ChromaDB
collection.add()call, causingbad allocationcrashes on machines with limited RAM. AddedBATCH_SIZE = 50cap andadd_drawers_batch()helper.Graceful Ctrl+C
Cancelling mid-run with Ctrl+C corrupts the palace. Added
SIGINThandler that sets aninterruptedflag, finishes the current file cleanly, then stops. Already-mined files are skipped on re-run, so progress is preserved.