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
use crateInitializeRequestParams;
/// State persisted to an external store for cross-instance session recovery.
///
/// When a client reconnects to a different server instance, the new instance
/// loads this state to transparently replay the `initialize` handshake without
/// the client needing to re-initialize.
/// Type alias for boxed session store errors.
pub type SessionStoreError = ;
/// Pluggable external session store for cross-instance recovery.
///
/// Implement this trait to back sessions with Redis, a database, or any
/// key-value store. The simplest usage is to set
/// `StreamableHttpServerConfig::session_store` to an `Arc<impl SessionStore>`.
///
/// # Example (in-memory, for testing)
///
/// ```rust,ignore
/// use std::{collections::HashMap, sync::Arc};
/// use tokio::sync::RwLock;
/// use rmcp::transport::streamable_http_server::session::store::{
/// SessionState, SessionStore, SessionStoreError,
/// };
///
/// #[derive(Default)]
/// struct InMemoryStore(Arc<RwLock<HashMap<String, SessionState>>>);
///
/// #[async_trait::async_trait]
/// impl SessionStore for InMemoryStore {
/// async fn load(&self, id: &str) -> Result<Option<SessionState>, SessionStoreError> {
/// Ok(self.0.read().await.get(id).cloned())
/// }
/// async fn store(&self, id: &str, state: &SessionState) -> Result<(), SessionStoreError> {
/// self.0.write().await.insert(id.to_owned(), state.clone());
/// Ok(())
/// }
/// async fn delete(&self, id: &str) -> Result<(), SessionStoreError> {
/// self.0.write().await.remove(id);
/// Ok(())
/// }
/// }
/// ```