1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//! The only acquisitions of the MCP server's shared store mutex (issue #275).
//!
//! The MCP server is a long-lived stdio process (`server.rs`), so a panic in
//! one request must not decide the fate of every later one. `unwrap()` on the
//! shared `Mutex<MemoryStore>` does: the first panic poisons the mutex and
//! every acquisition afterwards panics again inside the tool handler — a
//! permanent outage caused by one bad request. Both helpers here *answer* a
//! poisoned mutex with an internal error, so the request fails and the server
//! keeps serving.
//!
//! Neither helper recovers the guard with `into_inner()`/`clear_poison`: the
//! alternative to answering is serving on with state a panic may have left
//! half-written, and the poison is permanent for the process lifetime. The
//! opposite policy is right for a *test* mutex — `config::tests_utils`'s
//! `lock_env_mutex` recovers precisely so one panicking test does not cascade
//! `PoisonError` to its siblings. That reasoning does not transfer to a server
//! whose data a panic may have corrupted mid-transaction.
//!
//! Two helpers because the wrapper's own signatures differ: the tool-facing
//! methods return `rmcp::ErrorData` and the search/list methods return the
//! library `Error`, which `tools.rs` converts. Choose by the caller's return
//! type; they are not interchangeable — routing an `rmcp::ErrorData` method
//! through `lock_store` would answer with `Error::Database`'s `Database error:`
//! frame instead of the plain poison message.
use ;
use crateError;
use crateMemoryStore;
use McpError;
/// Acquire the shared store for the methods that answer in `rmcp::ErrorData`.
///
/// `op` names the acquiring wrapper method: std's `PoisonError` says nothing
/// about which acquisition failed, and in a stdio server this message is the
/// only channel an operator reads.
pub
/// Acquire the shared store for the methods that answer in the library `Error`.
///
/// `Error::Database` is the internal-style variant of the #255 surface:
/// `From<Error> for rmcp::ErrorData` renders it as `McpError::internal_error`,
/// i.e. the same `data.type == "internal_error"` a `lock_mcp` failure produces.
/// It must not become `Error::DatabaseLocked` — that variant tells an MCP
/// client to retry a lock that will never free.
pub
/// The message behind both helpers' poisoned answers, kept in one place so the
/// two return types cannot drift in what they tell the client. It always
/// *starts* with this crate's wording: the `Error::Database` frame that
/// `From<Error> for rmcp::ErrorData` prepends to the `lock_store` paths comes
/// before it, but nothing after that point is ours — std's `PoisonError`
/// Display closes the message, so a test pins the prefix and no more.