1use alloc::string::{String, ToString};
2use alloc::sync::Arc;
3use alloc::vec::Vec;
4
5use serde::Serialize;
6use serde::de::DeserializeOwned;
7use spin::Mutex;
8
9use crate::connection::{
10 ConnectionEvent, ConnectionLifecycle, ConnectionPool, ConnectionState, ResumeRequest,
11 SubscriptionId,
12};
13use crate::embedded::{
14 EmbeddedChannelHandle, EmbeddedConversationHandle, EmptyLifecycleStream, ReadyResult,
15 SdkSubscription,
16};
17use crate::{
18 ChannelHandle, ConversationHandle, ConversationId, DeliveryAck, PressureResponse,
19 SchemaValidate, SdkError,
20};
21
22pub use super::participant::RemoteParticipantHandle;
23
24use super::config::SdkConfig;
25use super::protocol::{
26 RemoteTransport, WireConversationRequest, WirePublishRequest, WireResumeRequest,
27 WireSubscribeRequest, deserialize_payload,
28};
29use super::{RemoteConfig, ServerAddress, connection_error};
30
31#[derive(Debug)]
32struct RemoteChannelState {
33 lifecycle: ConnectionLifecycle,
34 pool: ConnectionPool,
35 next_subscription: u64,
36}
37
38#[derive(Clone, Debug)]
40pub struct RemoteChannelHandle {
41 server_address: ServerAddress,
42 channel_name: String,
43 state: Arc<Mutex<RemoteChannelState>>,
44 transport: Arc<dyn RemoteTransport>,
45}
46
47impl RemoteChannelHandle {
48 pub fn new(config: &RemoteConfig) -> Result<Self, SdkError> {
54 Ok(Self {
55 server_address: config.server_address.clone(),
56 channel_name: config.channel_name.clone(),
57 state: Arc::new(Mutex::new(RemoteChannelState {
58 lifecycle: ConnectionLifecycle::new(),
59 pool: ConnectionPool::new(config.pool_config)?,
60 next_subscription: 0,
61 })),
62 transport: Arc::clone(&config.transport),
63 })
64 }
65
66 #[must_use]
68 pub fn connection_state(&self) -> ConnectionState {
69 self.state.lock().lifecycle.state().clone()
70 }
71
72 pub fn reconnect_started(&self) -> Result<(), SdkError> {
78 self.state.lock().lifecycle.reconnect_started()
79 }
80
81 pub fn connected(&self) -> Result<Vec<ResumeRequest>, SdkError> {
87 let requests = {
90 let mut state = self.state.lock();
91 let previous = state.lifecycle.state().clone();
92 state.lifecycle.connected()?;
93 let event = ConnectionEvent::new(previous, state.lifecycle.state().clone());
94 state.pool.resume_requests_for_transition(&event)?
95 };
96 for request in &requests {
97 let wire_request = WireResumeRequest::new(*request);
98 self.transport.resume(&self.server_address, &wire_request)?;
99 }
100 Ok(requests)
101 }
102
103 pub fn track_subscription(&self) -> Result<SubscriptionId, SdkError> {
109 let mut state = self.state.lock();
110 let id = SubscriptionId::new(state.next_subscription);
111 state.next_subscription =
112 state
113 .next_subscription
114 .checked_add(1)
115 .ok_or_else(|| SdkError::Store {
116 description: "subscription id overflow".to_string(),
117 })?;
118 state.pool.assign_subscription(id)?;
119 Ok(id)
120 }
121
122 pub fn acknowledge(
128 &self,
129 subscription_id: SubscriptionId,
130 sequence: u64,
131 ) -> Result<(), SdkError> {
132 let mut state = self.state.lock();
133 state.pool.acknowledge(subscription_id, sequence)
134 }
135
136 #[must_use]
138 pub const fn server_address(&self) -> &ServerAddress {
139 &self.server_address
140 }
141}
142
143impl ChannelHandle for RemoteChannelHandle {
144 type Subscription<M>
145 = SdkSubscription<M>
146 where
147 M: DeserializeOwned;
148
149 type ReplyFuture<'a, Resp>
150 = ReadyResult<Resp>
151 where
152 Self: 'a,
153 Resp: DeserializeOwned + 'a;
154
155 fn publish<M>(&self, message: M) -> Result<PressureResponse, SdkError>
156 where
157 M: Serialize + SchemaValidate,
158 {
159 let request = WirePublishRequest::new(&self.channel_name, &message)?;
160 self.transport.publish(&self.server_address, &request)
161 }
162
163 fn subscribe<M>(&self) -> Self::Subscription<M>
164 where
165 M: DeserializeOwned,
166 {
167 let outcome = self.track_subscription().and_then(|subscription_id| {
168 let connection_id = self
169 .state
170 .lock()
171 .pool
172 .connection_for_subscription(subscription_id)
173 .ok_or_else(|| connection_error("subscription was not assigned to the pool"))?;
174 let request = WireSubscribeRequest::new(
175 &self.channel_name,
176 subscription_id,
177 connection_id.get(),
178 )?;
179 self.transport.subscribe(&self.server_address, &request)
180 });
181
182 match outcome {
183 Ok(()) => SdkSubscription::empty(),
184 Err(error) => SdkSubscription::error(error),
185 }
186 }
187
188 fn request_reply<Req, Resp>(&self, request: Req) -> ReadyResult<Resp>
189 where
190 Req: Serialize + SchemaValidate,
191 Resp: DeserializeOwned,
192 {
193 ReadyResult::new(self.request_reply_blocking(&request))
194 }
195}
196
197impl RemoteChannelHandle {
198 pub fn publish_with_idempotency_key<M>(
213 &self,
214 message: &M,
215 idempotency_key: &str,
216 ) -> Result<DeliveryAck, SdkError>
217 where
218 M: Serialize + SchemaValidate,
219 {
220 let request =
221 WirePublishRequest::with_idempotency_key(&self.channel_name, message, idempotency_key)?;
222 self.transport
223 .publish_with_delivery(&self.server_address, &request)
224 }
225
226 fn request_reply_blocking<Req, Resp>(&self, request: &Req) -> Result<Resp, SdkError>
240 where
241 Req: Serialize + SchemaValidate,
242 Resp: DeserializeOwned,
243 {
244 let conversation_id = ConversationId::new(self.channel_name.clone());
245 let wire_request = WireConversationRequest::new(&conversation_id, request)?;
246 let reply = self
247 .transport
248 .request_reply_conversation(&self.server_address, &wire_request)?;
249 deserialize_payload(&reply)
250 }
251}
252
253#[derive(Clone, Debug)]
255pub struct RemoteConversationHandle {
256 server_address: ServerAddress,
257 conversation_id: ConversationId,
258 lifecycle: Arc<Mutex<ConnectionLifecycle>>,
259 transport: Arc<dyn RemoteTransport>,
260 pending_reply: Arc<Mutex<Option<Vec<u8>>>>,
265}
266
267impl RemoteConversationHandle {
268 #[must_use]
270 pub fn new(config: &RemoteConfig) -> Self {
271 Self {
272 server_address: config.server_address.clone(),
273 conversation_id: config.conversation_id.clone(),
274 lifecycle: Arc::new(Mutex::new(ConnectionLifecycle::new())),
275 transport: Arc::clone(&config.transport),
276 pending_reply: Arc::new(Mutex::new(None)),
277 }
278 }
279
280 pub fn request<Req>(&self, request: Req) -> Result<(), SdkError>
295 where
296 Req: Serialize,
297 {
298 let wire_request = WireConversationRequest::new(&self.conversation_id, &request)?;
299 let reply = self
300 .transport
301 .request_reply_conversation(&self.server_address, &wire_request)?;
302 *self.pending_reply.lock() = Some(reply);
303 Ok(())
304 }
305
306 #[must_use]
308 pub fn connection_state(&self) -> ConnectionState {
309 self.lifecycle.lock().state().clone()
310 }
311
312 #[must_use]
314 pub const fn server_address(&self) -> &ServerAddress {
315 &self.server_address
316 }
317}
318
319impl ConversationHandle for RemoteConversationHandle {
320 type ReceiveFuture<'a, M>
321 = ReadyResult<M>
322 where
323 Self: 'a,
324 M: DeserializeOwned + 'a;
325
326 type LifecycleStream = EmptyLifecycleStream;
327
328 fn send<M>(&self, message: M) -> Result<(), SdkError>
329 where
330 M: Serialize,
331 {
332 let request = WireConversationRequest::new(&self.conversation_id, &message)?;
333 self.transport
334 .send_conversation(&self.server_address, &request)
335 }
336
337 fn receive<M>(&self) -> ReadyResult<M>
338 where
339 M: DeserializeOwned,
340 {
341 ReadyResult::new(self.receive_blocking())
342 }
343
344 fn lifecycle(&self) -> Self::LifecycleStream {
345 EmptyLifecycleStream
346 }
347}
348
349impl RemoteConversationHandle {
350 fn receive_blocking<M>(&self) -> Result<M, SdkError>
359 where
360 M: DeserializeOwned,
361 {
362 let payload = self
363 .pending_reply
364 .lock()
365 .take()
366 .ok_or_else(|| SdkError::Conversation {
367 conversation_id: self.conversation_id.as_str().to_string(),
368 description: "no correlated reply is pending; call request before receive"
369 .to_string(),
370 })?;
371 deserialize_payload(&payload)
372 }
373}
374
375#[derive(Clone, Debug)]
377pub enum SdkChannelHandle {
378 Embedded(EmbeddedChannelHandle),
380 Remote(RemoteChannelHandle),
382}
383
384impl SdkChannelHandle {
385 pub fn new(config: &SdkConfig) -> Result<Self, SdkError> {
391 match config {
392 SdkConfig::Embedded(config) => Ok(Self::Embedded(EmbeddedChannelHandle::new(config))),
393 SdkConfig::Remote(config) => Ok(Self::Remote(RemoteChannelHandle::new(config)?)),
394 }
395 }
396}
397
398impl ChannelHandle for SdkChannelHandle {
399 type Subscription<M>
400 = SdkSubscription<M>
401 where
402 M: DeserializeOwned;
403
404 type ReplyFuture<'a, Resp>
405 = ReadyResult<Resp>
406 where
407 Self: 'a,
408 Resp: DeserializeOwned + 'a;
409
410 fn publish<M>(&self, message: M) -> Result<PressureResponse, SdkError>
411 where
412 M: Serialize + SchemaValidate,
413 {
414 match self {
415 Self::Embedded(handle) => handle.publish(message),
416 Self::Remote(handle) => handle.publish(message),
417 }
418 }
419
420 fn subscribe<M>(&self) -> Self::Subscription<M>
421 where
422 M: DeserializeOwned,
423 {
424 match self {
425 Self::Embedded(handle) => handle.subscribe(),
426 Self::Remote(handle) => handle.subscribe(),
427 }
428 }
429
430 fn request_reply<Req, Resp>(&self, request: Req) -> ReadyResult<Resp>
431 where
432 Req: Serialize + SchemaValidate,
433 Resp: DeserializeOwned,
434 {
435 match self {
436 Self::Embedded(handle) => handle.request_reply(request),
437 Self::Remote(handle) => handle.request_reply(request),
438 }
439 }
440}
441
442#[derive(Clone, Debug)]
444pub enum SdkConversationHandle {
445 Embedded(EmbeddedConversationHandle),
447 Remote(RemoteConversationHandle),
449}
450
451impl SdkConversationHandle {
452 pub fn new(config: &SdkConfig) -> Result<Self, SdkError> {
458 match config {
459 SdkConfig::Embedded(config) => {
460 Ok(Self::Embedded(EmbeddedConversationHandle::new(config)))
461 }
462 SdkConfig::Remote(config) => Ok(Self::Remote(RemoteConversationHandle::new(config))),
463 }
464 }
465}
466
467impl ConversationHandle for SdkConversationHandle {
468 type ReceiveFuture<'a, M>
469 = ReadyResult<M>
470 where
471 Self: 'a,
472 M: DeserializeOwned + 'a;
473
474 type LifecycleStream = EmptyLifecycleStream;
475
476 fn send<M>(&self, message: M) -> Result<(), SdkError>
477 where
478 M: Serialize,
479 {
480 match self {
481 Self::Embedded(handle) => handle.send(message),
482 Self::Remote(handle) => handle.send(message),
483 }
484 }
485
486 fn receive<M>(&self) -> ReadyResult<M>
487 where
488 M: DeserializeOwned,
489 {
490 match self {
491 Self::Embedded(handle) => handle.receive(),
492 Self::Remote(handle) => handle.receive(),
493 }
494 }
495
496 fn lifecycle(&self) -> Self::LifecycleStream {
497 EmptyLifecycleStream
498 }
499}