Skip to content

ENH: use SQLite for the directory index map - #764

Closed
d-chambers wants to merge 4 commits into
devfrom
index-map-sqlite
Closed

ENH: use SQLite for the directory index map#764
d-chambers wants to merge 4 commits into
devfrom
index-map-sqlite

Conversation

@d-chambers

@d-chambers d-chambers commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Description

This is the first focused extraction from the free-threaded integration PR #763. It replaces the unreleased JSON directory index map on dev with a small SQLite database.

The map now uses transactional upserts with BEGIN IMMEDIATE, per-operation connections, and a busy timeout so concurrent writers preserve every directory entry. Corrupt disposable maps are rebuilt under a content-independent advisory lock that coordinates threads and processes around destructive recovery.

The indexer retains its local-index fallback when the optional global map is unavailable. Read-only shared caches can reuse existing mappings through SQLite read-only mode, while corrupt read-only optional maps degrade safely for writable data directories. POSIX at-fork callbacks also wait for an active recovery guard to finish before forking, so a child cannot inherit process-local or advisory file-lock state. Platforms without fcntl, including relevant Emscripten builds, retain the single-process lock path.

This is an intentional clean break from the unreleased JSON format. Sibling cache_paths.json files are ignored and left untouched; the configured path always names the SQLite database.

PR #763 remains open as the integration reference and is not closed by this extraction.

Validation

  • PYTHON_GIL=0: 145 affected tests passed
  • PYTHON_GIL=1: 145 affected tests passed
  • TestIndexMap with DeprecationWarning treated as an error: 18 passed in each GIL mode
  • Repository hooks passed on all changed files
  • Fresh focused Claude review approved the post-review fixes; its one low-severity edge case was addressed with a regression
  • All actionable Codex review threads were addressed with regressions and resolved

Checklist

I have (if applicable):

  • referenced the related integration PR.
  • documented the new behavior with docstrings.
  • included tests. See testing guidelines.
  • added the "ready_for_review" tag once the PR is ready to be reviewed.

@d-chambers

Copy link
Copy Markdown
Contributor Author

@codex review

@d-chambers d-chambers added the ready_for_review PR is ready for review label Jul 22, 2026
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The directory index-location cache now uses SQLite instead of JSON. The indexer initializes and repairs corrupted databases, performs transactional upserts, handles concurrent recovery, and reads external changes. Configuration, fixtures, and tests now target SQLite behavior.

Changes

SQLite index-map cache

Layer / File(s) Summary
SQLite storage and recovery
dascore/config.py, dascore/io/index/indexer.py
The default cache path changes to cache_paths.sqlite3; SQLite schema initialization, corruption detection, recovery locking, and rebuild helpers replace JSON handling.
Transactional map operations
dascore/io/index/indexer.py
Directory-to-index mappings are read from SQLite and updated with transactional, conflict-safe upserts, while unavailable optional global maps are suppressed during lookup.
Configuration and behavioral validation
tests/conftest.py, tests/test_io/test_index/test_index_edge_cases.py, tests/test_io/test_indexer.py
Tests and fixtures validate SQLite paths, recovery, concurrency, error handling, out-of-band writes, and ignoring legacy JSON files.

Possibly related PRs

Suggested labels: IO

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly states the main change: switching the directory index map to SQLite.
Description check ✅ Passed The description covers the problem, implementation, validation, and checklist, matching the template well.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch index-map-sqlite

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added the IO Work for reading/writing different formats label Jul 22, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9c12800141

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread dascore/io/index/indexer.py
Comment thread dascore/io/index/indexer.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
dascore/io/index/indexer.py (1)

158-166: 🚀 Performance & Scalability | 🔵 Trivial

Exclusive recovery lock serializes all reads, not just recovery.

Every _get_index_map/_update_index_map acquires the in-process _INDEX_MAP_RECOVERY_LOCK and an exclusive OS file lock through _index_map_recovery_guard, so concurrent reads are fully serialized across threads and processes even when no recovery is in progress. The inline comment (Lines 162-165) documents this is deliberate to keep readers away from the unlink/rebuild window, and given how infrequently the map is touched this is a reasonable safety-over-throughput tradeoff.

If contention ever shows up on a hot path, consider a shared-lock-for-normal-access / exclusive-lock-for-recovery scheme (lock upgrade) so reads can proceed concurrently. No change needed for now.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dascore/io/index/indexer.py` around lines 158 - 166, The existing exclusive
locking in _run_index_map_operation and _index_map_recovery_guard is
intentional; make no code changes. Preserve serialization of reads and updates
across threads and processes to protect the database recovery window.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@dascore/io/index/indexer.py`:
- Around line 158-166: The existing exclusive locking in
_run_index_map_operation and _index_map_recovery_guard is intentional; make no
code changes. Preserve serialization of reads and updates across threads and
processes to protect the database recovery window.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1790dad0-8e48-4452-a5e2-7509f11fc87d

📥 Commits

Reviewing files that changed from the base of the PR and between 687dfbe and 9c12800.

📒 Files selected for processing (5)
  • dascore/config.py
  • dascore/io/index/indexer.py
  • tests/conftest.py
  • tests/test_io/test_index/test_index_edge_cases.py
  • tests/test_io/test_indexer.py

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0ac739f63c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread dascore/io/index/indexer.py Outdated
Comment thread dascore/io/index/indexer.py Outdated

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a187cbf2d4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread dascore/io/index/indexer.py
Comment thread dascore/io/index/indexer.py Outdated
Comment thread dascore/io/index/indexer.py

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: 6b91ca3fa4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@codecov

codecov Bot commented Jul 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.92754% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.91%. Comparing base (687dfbe) to head (6b91ca3).

Files with missing lines Patch % Lines
dascore/io/index/indexer.py 94.92% 7 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##              dev     #764       +/-   ##
===========================================
+ Coverage   48.75%   99.91%   +51.16%     
===========================================
  Files         163      163               
  Lines       17081    17330      +249     
===========================================
+ Hits         8327    17316     +8989     
+ Misses       8754       14     -8740     
Flag Coverage Δ
network 48.35% <20.28%> (-0.40%) ⬇️
unittests 99.90% <94.92%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@d-chambers

Copy link
Copy Markdown
Contributor Author

Superseded by #772, which takes a simpler approach: one small JSON file per data directory instead of a SQLite database with corruption-recovery locks and os.register_at_fork hooks. Same lost-update and #508 corruption guarantees for this disposable single-key cache, with far less machinery and no process-wide fork side effects. Leaving this open for reference; close whenever you're satisfied #772 covers it.

@d-chambers

Copy link
Copy Markdown
Contributor Author

superseded by #772

@d-chambers d-chambers closed this Jul 25, 2026
@d-chambers
d-chambers deleted the index-map-sqlite branch July 25, 2026 08:02
@d-chambers d-chambers removed the ready_for_review PR is ready for review label Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

IO Work for reading/writing different formats

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant