contextvm_sdk/transport/open_stream/
mod.rs1pub mod constants;
23pub mod errors;
24pub mod frame;
25pub mod receiver;
26pub mod registry;
27pub mod session;
28pub mod writer;
29
30pub use constants::*;
31pub use errors::OpenStreamError;
32pub use frame::{open_stream_frame_from_notification, OpenStreamFrame};
33pub use receiver::OpenStreamReceiver;
34pub use registry::{
35 OpenStreamRegistry, OpenStreamRegistryPolicy, OpenStreamSessionInit, RegistryAbortHook,
36 RegistryCloseHook,
37};
38pub use session::{
39 FrameOutcome, KeepaliveAction, OpenStreamSession, OpenStreamSessionOptions, PublishFrame,
40};
41pub use writer::{OnAbortHook, OnCloseHook, OpenStreamWriter, OpenStreamWriterOptions};
42
43#[derive(Debug, Clone)]
57#[non_exhaustive]
58pub struct OpenStreamConfig {
59 pub enabled: bool,
62 pub max_concurrent_streams: usize,
64 pub max_buffered_chunks_per_stream: usize,
66 pub max_buffered_bytes_per_stream: usize,
68 pub idle_timeout_ms: u64,
70 pub probe_timeout_ms: u64,
72 pub close_grace_period_ms: u64,
74 pub max_total_timeout_ms: Option<u64>,
80}
81
82impl Default for OpenStreamConfig {
83 fn default() -> Self {
84 Self {
85 enabled: false,
88 max_concurrent_streams: constants::DEFAULT_MAX_CONCURRENT_OPEN_STREAMS,
89 max_buffered_chunks_per_stream: constants::DEFAULT_MAX_BUFFERED_CHUNKS_PER_STREAM,
90 max_buffered_bytes_per_stream: constants::DEFAULT_MAX_BUFFERED_BYTES_PER_STREAM,
91 idle_timeout_ms: constants::DEFAULT_OPEN_STREAM_IDLE_TIMEOUT_MS,
92 probe_timeout_ms: constants::DEFAULT_OPEN_STREAM_PROBE_TIMEOUT_MS,
93 close_grace_period_ms: constants::DEFAULT_OPEN_STREAM_CLOSE_GRACE_PERIOD_MS,
94 max_total_timeout_ms: None,
95 }
96 }
97}
98
99impl OpenStreamConfig {
100 pub fn enabled() -> Self {
102 Self {
103 enabled: true,
104 ..Self::default()
105 }
106 }
107
108 pub fn with_enabled(mut self, enabled: bool) -> Self {
110 self.enabled = enabled;
111 self
112 }
113
114 pub fn with_max_concurrent_streams(mut self, max: usize) -> Self {
116 self.max_concurrent_streams = max;
117 self
118 }
119
120 pub fn with_max_buffered_chunks_per_stream(mut self, max: usize) -> Self {
122 self.max_buffered_chunks_per_stream = max;
123 self
124 }
125
126 pub fn with_max_buffered_bytes_per_stream(mut self, max: usize) -> Self {
128 self.max_buffered_bytes_per_stream = max;
129 self
130 }
131
132 pub fn with_idle_timeout_ms(mut self, ms: u64) -> Self {
134 self.idle_timeout_ms = ms;
135 self
136 }
137
138 pub fn with_probe_timeout_ms(mut self, ms: u64) -> Self {
140 self.probe_timeout_ms = ms;
141 self
142 }
143
144 pub fn with_close_grace_period_ms(mut self, ms: u64) -> Self {
146 self.close_grace_period_ms = ms;
147 self
148 }
149
150 pub fn with_max_total_timeout_ms(mut self, ms: Option<u64>) -> Self {
152 self.max_total_timeout_ms = ms;
153 self
154 }
155}
156
157impl From<&OpenStreamConfig> for OpenStreamRegistryPolicy {
158 fn from(config: &OpenStreamConfig) -> Self {
161 OpenStreamRegistryPolicy {
162 max_concurrent_streams: config.max_concurrent_streams,
163 max_buffered_chunks_per_stream: config.max_buffered_chunks_per_stream,
164 max_buffered_bytes_per_stream: config.max_buffered_bytes_per_stream,
165 idle_timeout_ms: config.idle_timeout_ms,
166 probe_timeout_ms: config.probe_timeout_ms,
167 close_grace_period_ms: config.close_grace_period_ms,
168 }
169 }
170}
171
172#[cfg(test)]
173mod config_tests {
174 use super::*;
175
176 #[test]
177 fn default_is_disabled_with_ts_parity_knobs() {
178 let config = OpenStreamConfig::default();
179 assert!(!config.enabled);
181 assert!(OpenStreamConfig::default().with_enabled(true).enabled);
183 assert!(OpenStreamConfig::enabled().enabled);
184 assert_eq!(config.max_concurrent_streams, 64);
185 assert_eq!(config.max_buffered_chunks_per_stream, 64);
186 assert_eq!(config.max_buffered_bytes_per_stream, 512 * 1024);
187 assert_eq!(config.idle_timeout_ms, 30_000);
188 assert_eq!(config.probe_timeout_ms, 20_000);
189 assert_eq!(config.close_grace_period_ms, 5_000);
190 assert_eq!(config.max_total_timeout_ms, None);
192 }
193
194 #[test]
195 fn builders_opt_in_and_override() {
196 let config = OpenStreamConfig::default()
197 .with_enabled(true)
198 .with_max_concurrent_streams(8)
199 .with_max_buffered_bytes_per_stream(1024)
200 .with_max_total_timeout_ms(Some(60_000));
201 assert!(config.enabled);
202 assert_eq!(config.max_concurrent_streams, 8);
203 assert_eq!(config.max_buffered_bytes_per_stream, 1024);
204 assert_eq!(config.max_total_timeout_ms, Some(60_000));
205
206 assert!(OpenStreamConfig::enabled().enabled);
207 }
208
209 #[test]
210 fn projects_into_registry_policy() {
211 let config = OpenStreamConfig::default()
212 .with_max_concurrent_streams(3)
213 .with_max_buffered_chunks_per_stream(5)
214 .with_max_buffered_bytes_per_stream(7)
215 .with_idle_timeout_ms(11)
216 .with_probe_timeout_ms(13)
217 .with_close_grace_period_ms(17);
218 let policy: OpenStreamRegistryPolicy = (&config).into();
219 assert_eq!(policy.max_concurrent_streams, 3);
220 assert_eq!(policy.max_buffered_chunks_per_stream, 5);
221 assert_eq!(policy.max_buffered_bytes_per_stream, 7);
222 assert_eq!(policy.idle_timeout_ms, 11);
223 assert_eq!(policy.probe_timeout_ms, 13);
224 assert_eq!(policy.close_grace_period_ms, 17);
225 }
226}