1use serde::{Deserialize, Serialize};
4
5use crate::core::event::Event;
6use crate::core::state::State;
7
8pub type SessionId = String;
10
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13pub struct Session {
14 pub id: SessionId,
16 pub app_name: String,
18 pub user_id: String,
20 #[serde(default)]
22 pub state: State,
23 #[serde(default)]
25 pub events: Vec<Event>,
26 #[serde(default)]
28 pub last_update_time: f64,
29}
30
31impl Session {
32 pub fn new(
34 app_name: impl Into<String>,
35 user_id: impl Into<String>,
36 id: impl Into<String>,
37 ) -> Self {
38 Self {
39 id: id.into(),
40 app_name: app_name.into(),
41 user_id: user_id.into(),
42 state: State::default(),
43 events: Vec::new(),
44 last_update_time: now_secs(),
45 }
46 }
47}
48
49#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
51pub struct SessionMeta {
52 pub id: SessionId,
54 pub app_name: String,
56 pub user_id: String,
58 pub last_update_time: f64,
60}
61
62pub fn now_secs() -> f64 {
64 let now = std::time::SystemTime::now()
65 .duration_since(std::time::UNIX_EPOCH)
66 .unwrap_or_default();
67 let secs = now.as_secs() as f64;
69 let nanos = f64::from(now.subsec_nanos()) / 1_000_000_000.0;
70 secs + nanos
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn session_round_trips() {
79 let s = Session::new("a", "u", "sess");
80 let j = serde_json::to_value(&s).unwrap();
81 let back: Session = serde_json::from_value(j).unwrap();
82 assert_eq!(s, back);
83 }
84}