Skip to content

fix: poison lock, use parking_lot#1651

Open
nikhilsinhaparseable wants to merge 2 commits into
parseablehq:mainfrom
nikhilsinhaparseable:parking_lot
Open

fix: poison lock, use parking_lot#1651
nikhilsinhaparseable wants to merge 2 commits into
parseablehq:mainfrom
nikhilsinhaparseable:parking_lot

Conversation

@nikhilsinhaparseable
Copy link
Copy Markdown
Contributor

@nikhilsinhaparseable nikhilsinhaparseable commented May 25, 2026

parking_lot in

  • Stream metadata
  • Stream writer
  • Streams struct

Summary by CodeRabbit

  • Refactor
    • Improved concurrency handling to avoid panic/unwrap failures when accessing in-memory stream state.
    • Replaced lock behavior across ingestion, compaction, HTTP endpoints, startup, and admin flows to propagate errors instead of crashing.
    • Reduced risk of runtime lock-related panics, improving overall stability and reliability during heavy load and maintenance operations.

Review Change Stack

parking_lot in
- Stream metadata
- Stream writer
- Streams struct
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a9428e22-d65b-4466-998d-911fa9a883b4

📥 Commits

Reviewing files that changed from the base of the PR and between 02272a3 and 6f7fb22.

📒 Files selected for processing (1)
  • src/parseable/streams.rs

Walkthrough

This PR migrates lock primitives from std::sync to parking_lot across Streams and consumers, removing LOCK_EXPECT, PoisonError variants, and expect/unwrap calls on lock acquisition while preserving existing public APIs and tenant/stream lookup error behavior.

Changes

Lock Poisoning Removal via parking_lot Migration

Layer / File(s) Summary
Parking Lot Integration in Streams
src/parseable/streams.rs
Imports parking_lot::{Mutex, RwLock} and updates Stream writer and metadata to use infallible locks. Stream methods (push, flush, recordbatches_cloned, clear, metadata getters/setters, and log-source helpers) switch from poison-aware patterns to direct .lock() / .read() / .write() calls.
Streams Registry Lock Migration
src/parseable/streams.rs
Updates Streams registry operations (get_or_create, delete, contains, len, list, list_internal_streams, flush_and_convert) and related tests to use direct .read() / .write() instead of .expect(LOCK_EXPECT).
Error Type Cleanup
src/parseable/staging/mod.rs
Removes StagingError::PoisonError variant and its std::sync::PoisonError import.
Consumer Site Lock Acquisition Updates
src/event/mod.rs, src/handlers/http/logstream.rs, src/handlers/http/modal/mod.rs, src/parseable/mod.rs, src/prism/logstream/mod.rs, src/rbac/map.rs
Removes LOCK_EXPECT imports and converts expect/unwrap patterns on lock reads to direct acquisition or ? propagation; tenant/stream lookup errors (TenantNotFound, StreamNotFound) remain unchanged.

Sequence Diagram

No sequence diagram generated; this PR is a lock API migration and error-handling cleanup without new multi-component sequential interactions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

for next release

Suggested reviewers

  • parmesant

Poem

🐰 I hopped through locks both old and new,
No more poisons, just parking_lot true,
Unwraps retired, expects set free,
Silent locks now guard fields for me,
Celebrate—code sleeps soundly under tree.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is incomplete and lacks critical details required by the template, including rationale, key changes explanation, and testing/documentation checklists. Add a detailed description section explaining the problem with poisoning locks, why parking_lot solves it, and complete all required checklist items in the template.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: replacing Rust's standard library poisoning locks with parking_lot locks to fix lock poisoning issues.
Docstring Coverage ✅ Passed Docstring coverage is 80.85% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/parseable/streams.rs (1)

1924-1924: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix test compilation: remove .expect() from parking_lot::RwLock::read()/write() guards

parking_lot::RwLock::read() and write() return guard types directly (e.g., RwLockReadGuard), not Result, so calling .expect(...) on them is a type error. Update these test lines: 1924, 1937, 1960, 2007.

🐛 Proposed fix
@@ -1921,7 +1921,7 @@ fn get_or_create_returns_existing_stream() {
         assert!(Arc::ptr_eq(&stream1, &stream2));
 
         // Verify the map contains only one entry
-        let guard = streams.read().expect("Failed to acquire read lock");
+        let guard = streams.read();
         assert_eq!(guard.len(), 1);
     }
@@ -1934,7 +1934,7 @@ fn create_and_return_new_stream_when_name_does_not_exist() {
         let ingestor_id = Some("new_ingestor".to_owned());
 
         // Assert the stream doesn't exist already
-        let mut guard = streams.write().expect("Failed to acquire read lock");
+        let mut guard = streams.write();
         assert_eq!(guard.len(), 0);
@@ -1957,7 +1957,7 @@ fn create_and_return_new_stream_when_name_does_not_exist() {
         assert_eq!(stream.ingestor_id, ingestor_id);
 
         // Assert that the stream is created
-        let guard = streams.read().expect("Failed to acquire read lock");
+        let guard = streams.read();
         assert_eq!(guard.len(), 1);
 
@@ -2004,7 +2004,7 @@ fn get_or_create_stream_concurrently() {
         assert!(Arc::ptr_eq(&stream1, &stream2));
 
         // Verify the map contains only one entry
-        let guard = streams.read().expect("Failed to acquire read lock");
+        let guard = streams.read();
         assert_eq!(guard.len(), 1);
     }
🤖 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/parseable/streams.rs` at line 1924, The tests call
parking_lot::RwLock::read()/write() and then call .expect(...) even though those
methods return guard types (RwLockReadGuard/RwLockWriteGuard) directly, causing
a type error; remove the .expect(...) calls and assign the guard directly (e.g.,
let guard = streams.read(); and similarly for streams.write()) wherever you see
streams.read().expect(...) or streams.write().expect(...), ensuring the rest of
the test uses the guard value as before.
🧹 Nitpick comments (1)
src/parseable/streams.rs (1)

1323-1330: 💤 Low value

Remove commented-out dead code.

The commented line at line 1329 is leftover from previous refactoring and should be removed.

🧹 Suggested cleanup
     pub fn delete(&self, stream_name: &str, tenant_id: &Option<String>) {
         let tenant_id = tenant_id.as_deref().unwrap_or(DEFAULT_TENANT);
         let mut guard = self.write();
         if let Some(tenant_streams) = guard.get_mut(tenant_id) {
             tenant_streams.remove(stream_name);
         }
-        // self.write().remove(stream_name);
     }
🤖 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/parseable/streams.rs` around lines 1323 - 1330, In the delete method,
remove the dead commented-out line "// self.write().remove(stream_name);"—keep
the existing implementation that resolves tenant_id via DEFAULT_TENANT, acquires
the write lock via self.write(), and removes the stream from tenant_streams;
simply delete the leftover commented code to clean up the function.
🤖 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.

Outside diff comments:
In `@src/parseable/streams.rs`:
- Line 1924: The tests call parking_lot::RwLock::read()/write() and then call
.expect(...) even though those methods return guard types
(RwLockReadGuard/RwLockWriteGuard) directly, causing a type error; remove the
.expect(...) calls and assign the guard directly (e.g., let guard =
streams.read(); and similarly for streams.write()) wherever you see
streams.read().expect(...) or streams.write().expect(...), ensuring the rest of
the test uses the guard value as before.

---

Nitpick comments:
In `@src/parseable/streams.rs`:
- Around line 1323-1330: In the delete method, remove the dead commented-out
line "// self.write().remove(stream_name);"—keep the existing implementation
that resolves tenant_id via DEFAULT_TENANT, acquires the write lock via
self.write(), and removes the stream from tenant_streams; simply delete the
leftover commented code to clean up the function.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 45c5ecbe-ca5d-4790-9675-7ac1ef5ccdac

📥 Commits

Reviewing files that changed from the base of the PR and between 138fea3 and 02272a3.

📒 Files selected for processing (8)
  • src/event/mod.rs
  • src/handlers/http/logstream.rs
  • src/handlers/http/modal/mod.rs
  • src/parseable/mod.rs
  • src/parseable/staging/mod.rs
  • src/parseable/streams.rs
  • src/prism/logstream/mod.rs
  • src/rbac/map.rs
💤 Files with no reviewable changes (2)
  • src/parseable/staging/mod.rs
  • src/rbac/map.rs

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 25, 2026
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.

1 participant