1#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9pub struct ClosedSessionSummary {
10 pub sid: SessionId,
12 pub status: SessionStatus,
14 pub role_count: usize,
16 pub local_type_entries: usize,
18 pub edge_count: usize,
20 pub edge_handler_count: usize,
22 pub auth_leaf_count: usize,
24 pub auth_tree_count: usize,
26 pub auth_root_count: usize,
28 pub epoch: usize,
30}
31
32impl ClosedSessionSummary {
33 fn from_session(session: &SessionState) -> Self {
34 Self {
35 sid: session.sid,
36 status: session.status.clone(),
37 role_count: session.roles.len(),
38 local_type_entries: session.local_types.len(),
39 edge_count: session.buffers.len(),
40 edge_handler_count: session.edge_handlers.len(),
41 auth_leaf_count: session.auth_leaves.values().map(Vec::len).sum(),
42 auth_tree_count: session.auth_trees.len(),
43 auth_root_count: session.auth_roots.len(),
44 epoch: session.epoch,
45 }
46 }
47
48 fn retained_bytes_estimate(&self) -> usize {
49 std::mem::size_of::<Self>().saturating_add(serialized_bytes(self))
50 }
51}
52
53#[derive(Debug, Clone)]
55pub struct SessionOpenPlan {
56 pub(crate) roles: Vec<String>,
57 pub(crate) role_ids: BTreeMap<String, u16>,
58 pub(crate) initial_types: Vec<(String, LocalTypeR, LocalTypeR)>,
59 pub(crate) edge_blueprint: Vec<((u16, u16), String, String)>,
60 pub(crate) active_branch_roles: Vec<String>,
61}
62
63impl SessionOpenPlan {
64 fn collect_protocol_edges(
65 role: &str,
66 local_type: &LocalTypeR,
67 role_ids: &BTreeMap<String, u16>,
68 edges: &mut BTreeSet<(u16, u16)>,
69 ) {
70 match local_type {
71 LocalTypeR::End | LocalTypeR::Var(_) => {}
72 LocalTypeR::Mu { body, .. } => {
73 Self::collect_protocol_edges(role, body, role_ids, edges);
74 }
75 LocalTypeR::Send { partner, branches } => {
76 if let (Some(from_id), Some(to_id)) = (role_ids.get(role), role_ids.get(partner)) {
77 if from_id != to_id {
78 edges.insert((*from_id, *to_id));
79 }
80 }
81 for (_, _, continuation) in branches {
82 Self::collect_protocol_edges(role, continuation, role_ids, edges);
83 }
84 }
85 LocalTypeR::Recv { partner, branches } => {
86 if let (Some(from_id), Some(to_id)) = (role_ids.get(partner), role_ids.get(role)) {
87 if from_id != to_id {
88 edges.insert((*from_id, *to_id));
89 }
90 }
91 for (_, _, continuation) in branches {
92 Self::collect_protocol_edges(role, continuation, role_ids, edges);
93 }
94 }
95 }
96 }
97
98 #[must_use]
105 pub fn new(roles: &[String], initial_types: &BTreeMap<String, LocalTypeR>) -> Self {
106 let role_ids = SessionState::build_role_ids(roles);
107 let mut planned_types = Vec::with_capacity(roles.len());
108 let mut active_branch_roles = Vec::new();
109 for role in roles {
110 if let Some(original) = initial_types.get(role) {
111 let current = unfold_mu(original);
112 if SessionState::branch_shape(¤t).is_some() {
113 active_branch_roles.push(role.clone());
114 }
115 planned_types.push((role.clone(), current, original.clone()));
116 }
117 }
118
119 let mut protocol_edges = BTreeSet::new();
120 for role in roles {
121 if let Some(original) = initial_types.get(role) {
122 Self::collect_protocol_edges(role, original, &role_ids, &mut protocol_edges);
123 }
124 }
125 let mut edge_blueprint = Vec::with_capacity(protocol_edges.len());
126 for (from_id, to_id) in protocol_edges {
127 let from = roles
128 .get(usize::from(from_id))
129 .expect("sender role id must index the session-open role set")
130 .clone();
131 let to = roles
132 .get(usize::from(to_id))
133 .expect("receiver role id must index the session-open role set")
134 .clone();
135 edge_blueprint.push(((from_id, to_id), from, to));
136 }
137
138 Self {
139 roles: roles.to_vec(),
140 role_ids,
141 initial_types: planned_types,
142 edge_blueprint,
143 active_branch_roles,
144 }
145 }
146
147 #[must_use]
149 pub fn roles(&self) -> &[String] {
150 &self.roles
151 }
152
153 #[must_use]
155 pub fn edge_blueprint(&self) -> &[((u16, u16), String, String)] {
156 &self.edge_blueprint
157 }
158}
159
160#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
162pub struct SessionStoreMemoryUsage {
163 pub live_sessions: usize,
165 pub live_closed_sessions: usize,
167 pub archived_closed_sessions: usize,
169 pub live_local_type_entries: usize,
171 pub live_buffer_count: usize,
173 pub live_buffered_messages: usize,
175 pub live_edge_handler_count: usize,
177 pub live_auth_leaf_count: usize,
179 pub live_auth_tree_count: usize,
181 pub live_auth_root_count: usize,
183 pub retained_bytes: SessionStoreRetainedBytes,
185}
186
187#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
189pub struct SessionStoreRetainedBytes {
190 pub live_sessions: usize,
192 pub archived_closed: usize,
194 pub local_types: usize,
196 pub buffers: usize,
198 pub traces: usize,
200 pub auth: usize,
202 pub handlers: usize,
204 pub total: usize,
206}
207
208pub type SessionId = usize;
210
211pub type HandlerId = String;
213type HandlerNumericId = u16;
214type LabelNumericId = u16;
215type EdgeKey = (u16, u16);
216type LocalBranches<'a> = &'a [(Label, Option<ValType>, LocalTypeR)];
217type HandlerIndexBuild = (
218 BTreeMap<HandlerId, HandlerNumericId>,
219 Vec<HandlerId>,
220 BTreeMap<EdgeKey, HandlerNumericId>,
221 Option<HandlerNumericId>,
222);
223
224#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
225pub(crate) enum BranchDirection {
226 Send,
227 Recv,
228}
229
230#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
231pub(crate) struct CachedBranch {
232 pub(crate) direction: BranchDirection,
233 pub(crate) partner: String,
234 pub(crate) expected_type: Option<ValType>,
235 pub(crate) continuation: LocalTypeR,
236}
237
238pub const DEFAULT_HANDLER_ID: &str = "default_handler";
240
241fn default_handler_id() -> HandlerId {
242 DEFAULT_HANDLER_ID.to_string()
243}
244
245fn serialized_bytes<T: Serialize>(value: &T) -> usize {
246 bincode::serialized_size(value)
247 .ok()
248 .and_then(|bytes| usize::try_from(bytes).ok())
249 .unwrap_or(0)
250}
251
252#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
254pub struct Edge {
255 pub sid: SessionId,
257 pub sender: String,
259 pub receiver: String,
261}
262
263impl Edge {
264 #[must_use]
266 pub fn new(sid: SessionId, sender: impl Into<String>, receiver: impl Into<String>) -> Self {
267 Self {
268 sid,
269 sender: sender.into(),
270 receiver: receiver.into(),
271 }
272 }
273}
274
275#[derive(Debug, Deserialize)]
276struct EdgeJson {
277 sid: Option<SessionId>,
278 sender: String,
279 receiver: String,
280}
281
282pub fn decode_edge_json(
288 value: &JsonValue,
289 session_hint: Option<SessionId>,
290) -> Result<Edge, String> {
291 let raw: EdgeJson =
292 serde_json::from_value(value.clone()).map_err(|e| format!("invalid edge json: {e}"))?;
293
294 let sid = raw
295 .sid
296 .or(session_hint)
297 .ok_or_else(|| "missing sid in edge json".to_string())?;
298 Ok(Edge::new(sid, raw.sender, raw.receiver))
299}
300
301#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
303pub enum SessionStatus {
304 Active,
306 Draining,
308 Closed,
310 Cancelled,
312 Faulted {
314 reason: String,
316 },
317}
318
319#[derive(Debug, Clone, Serialize, Deserialize)]
321pub struct TypeEntry {
322 pub current: LocalTypeR,
324 pub original: LocalTypeR,
326}