Skip to main content

synd_runtime/session/
mod.rs

1use std::time::Duration;
2
3use crate::{CapabilitySet, Result};
4#[cfg(test)]
5pub(crate) use renewal::SessionRenewalObserver;
6use renewal::{SessionLeaseRenewal, SessionLeaseRenewalHandle, SessionRenewalSchedule};
7use synd_protocol::{
8    capability,
9    session::{CloseSessionRequest, SessionId, SessionLease},
10};
11
12mod renewal;
13
14pub struct Session {
15    client: synd_client::Client,
16    available_capabilities: CapabilitySet,
17    handle: Handle,
18}
19
20impl Session {
21    pub fn new(
22        client: synd_client::Client,
23        available_capabilities: CapabilitySet,
24        handle: Handle,
25    ) -> Self {
26        Self {
27            client,
28            available_capabilities,
29            handle,
30        }
31    }
32
33    pub fn client(&self) -> &synd_client::Client {
34        &self.client
35    }
36
37    pub fn available_capabilities(&self) -> &CapabilitySet {
38        &self.available_capabilities
39    }
40
41    pub async fn close(self) -> Result<()> {
42        self.handle.close().await
43    }
44}
45
46pub struct Handle {
47    kind: HandleKind,
48}
49
50enum HandleKind {
51    Inert,
52    Daemon(Box<DaemonSessionHandle>),
53}
54
55impl Handle {
56    pub fn inert() -> Self {
57        Self {
58            kind: HandleKind::Inert,
59        }
60    }
61
62    #[cfg(not(test))]
63    pub(crate) fn daemon(
64        client: synd_client::Client,
65        session_id: SessionId,
66        lease: SessionLease,
67    ) -> Self {
68        Self {
69            kind: HandleKind::Daemon(Box::new(DaemonSessionHandle::new(
70                client, session_id, lease,
71            ))),
72        }
73    }
74
75    #[cfg(test)]
76    pub(crate) fn daemon(
77        client: synd_client::Client,
78        session_id: SessionId,
79        lease: SessionLease,
80        renewal_observer: Option<SessionRenewalObserver>,
81    ) -> Self {
82        Self {
83            kind: HandleKind::Daemon(Box::new(DaemonSessionHandle::new(
84                client,
85                session_id,
86                lease,
87                renewal_observer,
88            ))),
89        }
90    }
91
92    pub async fn close(self) -> Result<()> {
93        match self.kind {
94            HandleKind::Inert => Ok(()),
95            HandleKind::Daemon(handle) => handle.close().await,
96        }
97    }
98}
99
100/// Client-side handle used to close an accepted daemon session.
101struct DaemonSessionHandle {
102    client: synd_client::Client,
103    session_id: SessionId,
104    renewal: SessionLeaseRenewalHandle,
105}
106
107impl DaemonSessionHandle {
108    #[cfg(not(test))]
109    fn new(client: synd_client::Client, session_id: SessionId, lease: SessionLease) -> Self {
110        let renewal = {
111            let schedule = SessionRenewalSchedule::from_lease(lease);
112            SessionLeaseRenewal::new(client.clone(), session_id.clone(), schedule).spawn()
113        };
114
115        Self {
116            client,
117            session_id,
118            renewal,
119        }
120    }
121
122    #[cfg(test)]
123    fn new(
124        client: synd_client::Client,
125        session_id: SessionId,
126        lease: SessionLease,
127        renewal_observer: Option<SessionRenewalObserver>,
128    ) -> Self {
129        let renewal = {
130            let schedule = SessionRenewalSchedule::from_lease(lease);
131            SessionLeaseRenewal::new(
132                client.clone(),
133                session_id.clone(),
134                schedule,
135                renewal_observer,
136            )
137            .spawn()
138        };
139
140        Self {
141            client,
142            session_id,
143            renewal,
144        }
145    }
146
147    async fn close(self) -> Result<()> {
148        self.renewal.stop().await;
149        self.client
150            .close_session(CloseSessionRequest::new(self.session_id))
151            .await?;
152
153        Ok(())
154    }
155}
156
157#[derive(Debug, Clone)]
158pub struct Config {
159    acquire_timeout: Duration,
160    #[cfg(test)]
161    renewal_observer: Option<SessionRenewalObserver>,
162}
163
164impl Config {
165    pub fn new(acquire_timeout: Duration) -> Self {
166        Self {
167            acquire_timeout,
168            #[cfg(test)]
169            renewal_observer: None,
170        }
171    }
172
173    pub fn acquire_timeout(&self) -> Duration {
174        self.acquire_timeout
175    }
176
177    #[cfg(test)]
178    pub(crate) fn with_renewal_observer(mut self, observer: SessionRenewalObserver) -> Self {
179        self.renewal_observer = Some(observer);
180        self
181    }
182
183    #[cfg(test)]
184    pub(crate) fn renewal_observer(&self) -> Option<SessionRenewalObserver> {
185        self.renewal_observer.clone()
186    }
187}
188
189impl PartialEq for Config {
190    fn eq(&self, other: &Self) -> bool {
191        self.acquire_timeout == other.acquire_timeout
192    }
193}
194
195impl Eq for Config {}
196
197impl Default for Config {
198    fn default() -> Self {
199        Self::new(Duration::from_secs(5))
200    }
201}
202
203#[derive(Debug, Clone, PartialEq, Eq)]
204pub struct Requirements {
205    required_capabilities: CapabilitySet,
206}
207
208impl Requirements {
209    pub fn new(required_capabilities: CapabilitySet) -> Self {
210        Self {
211            required_capabilities,
212        }
213    }
214
215    pub fn required_capabilities(&self) -> &CapabilitySet {
216        &self.required_capabilities
217    }
218}
219
220impl Default for Requirements {
221    fn default() -> Self {
222        Self::new(capability::local_api_capabilities())
223    }
224}