Implement SQLite-backed mtime state store#3186
Conversation
This module implements a SQLite-backed state store for tracking file modification times, allowing the vault file watcher to detect changes efficiently. It includes functions for recording seen files, marking files as deleted, retrieving last modification times, and loading all non-deleted states.
📝 WalkthroughWalkthroughThis PR introduces a new Rust module that implements an SQLite-backed persistent state store for tracking vault file modification times and deletion status. The store provides methods to record file mtimes, mark files as deleted, query last-seen mtimes, and bulk-load all tracked file states, with comprehensive unit tests validating the complete behavior. ChangesVault file watcher state persistence
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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: 1
🧹 Nitpick comments (2)
src/openhuman/workspace/state.rs (2)
32-104: ⚡ Quick winAdd debug/trace instrumentation around the new state-store operations.
This new persistence boundary has no diagnostics, so watcher/state drift on startup will be hard to triage. Please add stable, grep-friendly
debug/traceevents aroundopen,record_seen,record_deleted,last_mtime, andload_all, with correlation fields and redacted path data rather than raw file paths.As per coding guidelines, "In Rust, default to verbose diagnostics on new/changed flows using
log/tracingatdebug/tracelevels with stable grep-friendly prefixes and correlation fields" and "Never log secrets or full PII — redact sensitive information in logs".🤖 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 `@src/openhuman/workspace/state.rs` around lines 32 - 104, Add verbose, grep-friendly tracing/logging around the WatcherStateStore persistence methods (open, record_seen, record_deleted, last_mtime, load_all): emit a debug/trace event at method entry and on notable outcomes (success/failure) using a stable prefix like "watcher::state::" and include a correlation field (e.g., request_id or op_id) and redacted path (e.g., show only file name or hashed/obfuscated path) rather than raw paths; ensure errors returned from Connection::open and SQL operations are logged with their error details (but not full path), and use tracing::debug!/trace! (or log::debug!) consistently so callers can grep "watcher::state::" to find events.
115-169: ⚡ Quick winAdd a reopen test for the actual persistence contract.
All current tests exercise a single open connection. The PR’s core behavior is persistence across restarts, so this needs one case that writes state, drops the store, reopens the same SQLite file, and re-asserts
last_mtime/load_all.🤖 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 `@src/openhuman/workspace/state.rs` around lines 115 - 169, Add a test that verifies persistence across restarts: create a NamedTempFile, open a WatcherStateStore with WatcherStateStore::open(temp.path()), call record_seen (and optionally record_deleted), drop or let the store go out of scope, then reopen a new WatcherStateStore with the same temp.path() and assert last_mtime and load_all return the previously written values; keep the NamedTempFile alive for the duration of the test so the SQLite file is not removed. Reference: create NamedTempFile, WatcherStateStore::open, record_seen, record_deleted, last_mtime, load_all, and name the test e.g. reopen_persists_state.
🤖 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.
Inline comments:
In `@src/openhuman/workspace/state.rs`:
- Around line 86-103: The load_all function currently selects all rows from
vault_watcher_state and returns tombstones despite its contract to seed only
active (non-deleted) state; change the SQL in load_all (in function load_all) to
filter out deleted rows (e.g. add WHERE deleted = 0/false) so only non-deleted
FileState entries are returned, keep the existing row mapping (path, mtime_secs,
deleted) but you can drop reading the deleted column if you prefer since it will
always be false after the filter; ensure the returned mtime conversion and types
remain unchanged.
---
Nitpick comments:
In `@src/openhuman/workspace/state.rs`:
- Around line 32-104: Add verbose, grep-friendly tracing/logging around the
WatcherStateStore persistence methods (open, record_seen, record_deleted,
last_mtime, load_all): emit a debug/trace event at method entry and on notable
outcomes (success/failure) using a stable prefix like "watcher::state::" and
include a correlation field (e.g., request_id or op_id) and redacted path (e.g.,
show only file name or hashed/obfuscated path) rather than raw paths; ensure
errors returned from Connection::open and SQL operations are logged with their
error details (but not full path), and use tracing::debug!/trace! (or
log::debug!) consistently so callers can grep "watcher::state::" to find events.
- Around line 115-169: Add a test that verifies persistence across restarts:
create a NamedTempFile, open a WatcherStateStore with
WatcherStateStore::open(temp.path()), call record_seen (and optionally
record_deleted), drop or let the store go out of scope, then reopen a new
WatcherStateStore with the same temp.path() and assert last_mtime and load_all
return the previously written values; keep the NamedTempFile alive for the
duration of the test so the SQLite file is not removed. Reference: create
NamedTempFile, WatcherStateStore::open, record_seen, record_deleted, last_mtime,
load_all, and name the test e.g. reopen_persists_state.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 21b0755e-d85b-4ab6-b8e4-08e4997e5251
📒 Files selected for processing (1)
src/openhuman/workspace/state.rs
graycyrus
left a comment
There was a problem hiding this comment.
@manucian-official heads up — CI is failing on this PR (Rust Tauri Coverage is red), so i'll hold off on a full approve until that's sorted out. i did spot a couple things while going through the diff though:
The bigger one: state.rs is added to src/openhuman/workspace/ but workspace/mod.rs has no mod state; or pub mod state; declaration. The Rust compiler won't process this file at all — the module and its unit tests are effectively dead code. Nothing in the crate can reach WatcherStateStore until you add the declaration. This needs to be wired in before the PR does anything useful.
Smaller one inline below.
Fix the module declaration and the CI failure, and i'll come back for a full pass.
|
@coderabbitai can u pls summarize the changes in this PR? pros/cons? |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
cat src/openhuman/workspace/state.rsLength of output: 5683
What It DoesThis PR introduces a new Rust module ( SchemaCREATE TABLE IF NOT EXISTS vault_watcher_state (
path TEXT PRIMARY KEY,
mtime_secs INTEGER NOT NULL,
deleted INTEGER NOT NULL DEFAULT 0
);Key API
✅ Pros
|
…gging + tests - Add `pub mod state;` to workspace/mod.rs so the module is reachable (addresses @graycyrus blocker — file was dead code without it) - Filter deleted rows in load_all() with WHERE deleted = 0 to match its documented "non-deleted states" contract (addresses @coderabbitai) - Move `use rusqlite::OptionalExtension` to top-level imports (addresses @graycyrus inline comment) - Add debug/trace logging with [watcher::state] prefix on open, record_seen, record_deleted, load_all (addresses @coderabbitai nitpick, CLAUDE.md diagnostic logging requirement) - Add reopen_persists_state test verifying persistence across restarts (addresses @coderabbitai nitpick) - Update load_all_excludes_deleted test to assert filtered behavior
for my issue
Summary by CodeRabbit