Skip to content

Add concurrency hardening: file locking, write ordering, cancellation…#3

Open
jayanth-gensee wants to merge 1 commit into
GenseeAI:mainfrom
jayanth-gensee:solve-concurrency-branch
Open

Add concurrency hardening: file locking, write ordering, cancellation…#3
jayanth-gensee wants to merge 1 commit into
GenseeAI:mainfrom
jayanth-gensee:solve-concurrency-branch

Conversation

@jayanth-gensee

@jayanth-gensee jayanth-gensee commented Jun 26, 2026

Copy link
Copy Markdown

This PR addresses the issue #2.

JSONL appends now use std File::lock/unlock for mutual exclusion, write ordering is JSONL-before-DB so the append-only audit trail never loses records, artifact reads support best-effort cancellation on timeout, and Arc is re-exported crate-wide for consistency. Adds concurrency_tests module exercising parallel store writes.

Summary

File locking for JSONL appends
The append_jsonl in lib.rs now uses std::fs::File::lock()/unlock() to hold an exclusive flock while writing. This prevents interleaved writes from concurrent threads or processes (e.g. the daemon serving multiple connections). Uses the std API instead of raw libc::flock, so no unsafe and no libc dependency.

JSONL-before-DB write ordering
All append_* methods (append_session, append_hook_event, append_process_observation, etc.) in lib.rs now write to the JSONL file first, then to SQLite. If the DB write fails, the event is still in the append-only audit trail. Previously it was DB-first, meaning a DB failure could lose the JSONL record too.

Best-effort cancellation for timed-out artifact reads read_small_artifact_content_with_timeout now uses an AtomicBool flag shared with the spawned reader thread. On timeout, the flag is set so the thread can skip work if it hasn't started the blocking read yet.

Crate-wide Arc re-export
Arc added to the crate-wide re-exports alongside mpsc. Usage sites in preexec.rs and tests.rs updated from std::sync::Arc to Arc.

Concurrency test suite
New tests exercising parallel store writes, including multi-thread JSONL appends, shared Arc daemon-style writes, mixed event type contention, and concurrent read/write scenarios. Uses Barrier to force simultaneous thread starts.

Testing

Run all concurrency tests

cargo test -p gensee-crate-store concurrency_tests

Run a specific one

cargo test -p gensee-crate-store concurrency_tests::concurrent_jsonl_appends_should_not_interleave

…, and tests

JSONL appends now use std File::lock/unlock for mutual exclusion,
write ordering is JSONL-before-DB so the append-only audit trail never
loses records, artifact reads support best-effort cancellation on
timeout, and Arc is re-exported crate-wide for consistency. Adds
concurrency_tests module exercising parallel store writes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@yiying-zhang

yiying-zhang commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

I feel most of these cases are quite rare. Have you tried to reproduce them? What are the chance of these cases happening? As long as we have some fallback methods, we should not over-complicate the code base.

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.

3 participants