1use crate::{
2 validate_value, BootError, BoxFuture, ExecutionContext, ExecutionInterceptor,
3 ExecutionTransportKind, Guard, Result, Validate,
4};
5use serde::de::DeserializeOwned;
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8use std::future::Future;
9use std::ops::Deref;
10use std::sync::Arc;
11
12#[cfg(feature = "grpc-transport")]
13mod grpc;
14#[cfg(feature = "kafka-transport")]
15mod kafka;
16#[cfg(feature = "mqtt-transport")]
17mod mqtt;
18#[cfg(feature = "nats-transport")]
19mod nats;
20#[cfg(feature = "rabbitmq-transport")]
21mod rabbitmq;
22#[cfg(feature = "redis-transport")]
23mod redis;
24#[cfg(feature = "tcp-transport")]
25mod tcp;
26
27#[cfg(feature = "grpc-transport")]
28pub use self::grpc::{GrpcTransport, GrpcTransportClient, GrpcTransportOptions};
29#[cfg(feature = "kafka-transport")]
30pub use self::kafka::{KafkaTransport, KafkaTransportClient, KafkaTransportOptions};
31#[cfg(feature = "mqtt-transport")]
32pub use self::mqtt::{MqttTransport, MqttTransportClient, MqttTransportOptions, MqttTransportQoS};
33#[cfg(feature = "nats-transport")]
34pub use self::nats::{NatsTransport, NatsTransportClient, NatsTransportOptions};
35#[cfg(feature = "rabbitmq-transport")]
36pub use self::rabbitmq::{RabbitMqTransport, RabbitMqTransportClient, RabbitMqTransportOptions};
37#[cfg(feature = "redis-transport")]
38pub use self::redis::{RedisTransport, RedisTransportClient, RedisTransportOptions};
39#[cfg(feature = "tcp-transport")]
40pub use tcp::{TcpTransport, TcpTransportClient, TcpTransportOptions};
41
42#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
44pub struct TransportMessage {
45 pub pattern: String,
46 #[serde(default)]
47 pub data: Value,
48}
49
50impl TransportMessage {
51 pub fn new(pattern: impl Into<String>, data: impl Into<Value>) -> Self {
52 Self {
53 pattern: pattern.into(),
54 data: data.into(),
55 }
56 }
57
58 pub fn pattern(&self) -> &str {
59 &self.pattern
60 }
61
62 pub fn data(&self) -> &Value {
63 &self.data
64 }
65
66 pub fn text(pattern: impl Into<String>, data: impl Into<String>) -> Self {
67 Self::new(pattern, Value::String(data.into()))
68 }
69
70 pub fn json<T>(pattern: impl Into<String>, data: &T) -> Result<Self>
71 where
72 T: Serialize,
73 {
74 Ok(Self::new(
75 pattern,
76 serde_json::to_value(data).map_err(|err| BootError::Internal(err.to_string()))?,
77 ))
78 }
79
80 pub fn data_as<T>(&self) -> Result<T>
81 where
82 T: DeserializeOwned,
83 {
84 serde_json::from_value(self.data.clone())
85 .map_err(|err| BootError::BadRequest(err.to_string()))
86 }
87
88 pub fn validated_data<T>(&self) -> Result<T>
89 where
90 T: DeserializeOwned + Validate,
91 {
92 validate_value(self.data_as::<T>()?)
93 }
94}
95
96#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
98pub struct TransportReply {
99 #[serde(default)]
100 pub data: Value,
101}
102
103impl TransportReply {
104 pub fn new(data: impl Into<Value>) -> Self {
105 Self { data: data.into() }
106 }
107
108 pub fn data(&self) -> &Value {
109 &self.data
110 }
111
112 pub fn text(data: impl Into<String>) -> Self {
113 Self::new(Value::String(data.into()))
114 }
115
116 pub fn json<T>(data: &T) -> Result<Self>
117 where
118 T: Serialize,
119 {
120 Ok(Self::new(
121 serde_json::to_value(data).map_err(|err| BootError::Internal(err.to_string()))?,
122 ))
123 }
124
125 pub fn data_as<T>(&self) -> Result<T>
126 where
127 T: DeserializeOwned,
128 {
129 serde_json::from_value(self.data.clone())
130 .map_err(|err| BootError::BadRequest(err.to_string()))
131 }
132}
133
134pub trait IntoTransportReply {
136 fn into_transport_reply(self) -> Option<TransportReply>;
137}
138
139impl IntoTransportReply for TransportReply {
140 fn into_transport_reply(self) -> Option<TransportReply> {
141 Some(self)
142 }
143}
144
145impl IntoTransportReply for Option<TransportReply> {
146 fn into_transport_reply(self) -> Option<TransportReply> {
147 self
148 }
149}
150
151impl IntoTransportReply for Value {
152 fn into_transport_reply(self) -> Option<TransportReply> {
153 Some(TransportReply::new(self))
154 }
155}
156
157impl IntoTransportReply for Option<Value> {
158 fn into_transport_reply(self) -> Option<TransportReply> {
159 self.map(TransportReply::new)
160 }
161}
162
163impl IntoTransportReply for () {
164 fn into_transport_reply(self) -> Option<TransportReply> {
165 None
166 }
167}
168
169#[derive(Debug, Clone, Copy, PartialEq, Eq)]
170pub enum MessagePatternKind {
171 RequestResponse,
172 Event,
173}
174
175impl MessagePatternKind {
176 pub fn as_str(self) -> &'static str {
177 match self {
178 Self::RequestResponse => "request-response",
179 Self::Event => "event",
180 }
181 }
182}
183
184#[derive(Debug, Clone)]
186pub struct TransportContext {
187 pub pattern: String,
188 pub kind: MessagePatternKind,
189 pub module_name: Option<String>,
190 execution_context: ExecutionContext,
191}
192
193impl TransportContext {
194 fn new(definition: &MessagePatternDefinition, pattern: &str) -> Self {
195 let pattern = pattern.to_string();
196 let kind = definition.kind;
197 let module_name = definition.module_name.clone();
198 let execution_context = ExecutionContext::transport(
199 pattern.clone(),
200 ExecutionTransportKind::from(kind),
201 module_name.clone(),
202 );
203 Self {
204 pattern,
205 kind,
206 module_name,
207 execution_context,
208 }
209 }
210
211 pub fn execution_context(&self) -> &ExecutionContext {
212 &self.execution_context
213 }
214
215 pub fn into_execution_context(self) -> ExecutionContext {
216 self.execution_context
217 }
218}
219
220impl Deref for TransportContext {
221 type Target = ExecutionContext;
222
223 fn deref(&self) -> &Self::Target {
224 self.execution_context()
225 }
226}
227
228impl From<MessagePatternKind> for ExecutionTransportKind {
229 fn from(kind: MessagePatternKind) -> Self {
230 match kind {
231 MessagePatternKind::RequestResponse => Self::RequestResponse,
232 MessagePatternKind::Event => Self::Event,
233 }
234 }
235}
236
237pub trait TransportPipe: Send + Sync + 'static {
239 fn transform(&self, message: TransportMessage) -> BoxFuture<'static, Result<TransportMessage>>;
240}
241
242impl<F, Fut> TransportPipe for F
243where
244 F: Fn(TransportMessage) -> Fut + Send + Sync + 'static,
245 Fut: Future<Output = Result<TransportMessage>> + Send + 'static,
246{
247 fn transform(&self, message: TransportMessage) -> BoxFuture<'static, Result<TransportMessage>> {
248 Box::pin(self(message))
249 }
250}
251
252pub trait TransportGuard: Send + Sync + 'static {
254 fn can_activate(&self, context: TransportContext) -> BoxFuture<'static, Result<bool>>;
255}
256
257impl<F, Fut> TransportGuard for F
258where
259 F: Fn(TransportContext) -> Fut + Send + Sync + 'static,
260 Fut: Future<Output = Result<bool>> + Send + 'static,
261{
262 fn can_activate(&self, context: TransportContext) -> BoxFuture<'static, Result<bool>> {
263 Box::pin(self(context))
264 }
265}
266
267struct ExecutionTransportGuard<G> {
268 inner: G,
269}
270
271impl<G> TransportGuard for ExecutionTransportGuard<G>
272where
273 G: Guard,
274{
275 fn can_activate(&self, context: TransportContext) -> BoxFuture<'static, Result<bool>> {
276 self.inner.can_activate(context.into_execution_context())
277 }
278}
279
280pub trait TransportInterceptor: Send + Sync + 'static {
282 fn before(&self, _context: TransportContext) -> BoxFuture<'static, Result<()>> {
283 Box::pin(async { Ok(()) })
284 }
285
286 fn after(
287 &self,
288 _context: TransportContext,
289 reply: Option<TransportReply>,
290 ) -> BoxFuture<'static, Result<Option<TransportReply>>> {
291 Box::pin(async move { Ok(reply) })
292 }
293}
294
295struct ExecutionTransportInterceptor<I> {
296 inner: I,
297}
298
299impl<I> TransportInterceptor for ExecutionTransportInterceptor<I>
300where
301 I: ExecutionInterceptor,
302{
303 fn before(&self, context: TransportContext) -> BoxFuture<'static, Result<()>> {
304 self.inner.before(context.into_execution_context())
305 }
306
307 fn after(
308 &self,
309 context: TransportContext,
310 reply: Option<TransportReply>,
311 ) -> BoxFuture<'static, Result<Option<TransportReply>>> {
312 let future = self.inner.after(context.into_execution_context());
313 Box::pin(async move {
314 future.await?;
315 Ok(reply)
316 })
317 }
318}
319
320type TransportHandlerFuture = BoxFuture<'static, Result<Option<TransportReply>>>;
321type MessageValidator = Arc<dyn Fn(&TransportMessage) -> Result<()> + Send + Sync>;
322
323trait TransportMessageHandler: Send + Sync + 'static {
324 fn call(&self, message: TransportMessage) -> TransportHandlerFuture;
325}
326
327struct TransportHandlerAdapter<H> {
328 handler: H,
329}
330
331impl<H, Fut, R> TransportMessageHandler for TransportHandlerAdapter<H>
332where
333 H: Fn(TransportMessage) -> Fut + Send + Sync + 'static,
334 Fut: Future<Output = Result<R>> + Send + 'static,
335 R: IntoTransportReply + Send + 'static,
336{
337 fn call(&self, message: TransportMessage) -> TransportHandlerFuture {
338 let future = (self.handler)(message);
339 Box::pin(async move { Ok(future.await?.into_transport_reply()) })
340 }
341}
342
343#[derive(Clone)]
345pub struct MessagePatternDefinition {
346 pattern: String,
347 kind: MessagePatternKind,
348 handler: Arc<dyn TransportMessageHandler>,
349 pipes: Vec<Arc<dyn TransportPipe>>,
350 guards: Vec<Arc<dyn TransportGuard>>,
351 interceptors: Vec<Arc<dyn TransportInterceptor>>,
352 validators: Vec<MessageValidator>,
353 module_name: Option<String>,
354}
355
356impl MessagePatternDefinition {
357 pub fn request<H, Fut, R>(pattern: impl Into<String>, handler: H) -> Result<Self>
358 where
359 H: Fn(TransportMessage) -> Fut + Send + Sync + 'static,
360 Fut: Future<Output = Result<R>> + Send + 'static,
361 R: IntoTransportReply + Send + 'static,
362 {
363 Self::new(pattern, MessagePatternKind::RequestResponse, handler)
364 }
365
366 pub fn event<H, Fut>(pattern: impl Into<String>, handler: H) -> Result<Self>
367 where
368 H: Fn(TransportMessage) -> Fut + Send + Sync + 'static,
369 Fut: Future<Output = Result<()>> + Send + 'static,
370 {
371 Self::new(pattern, MessagePatternKind::Event, handler)
372 }
373
374 pub fn request_json<T, H, Fut, R>(pattern: impl Into<String>, handler: H) -> Result<Self>
375 where
376 T: DeserializeOwned + Send + 'static,
377 H: Fn(T) -> Fut + Send + Sync + 'static,
378 Fut: Future<Output = Result<R>> + Send + 'static,
379 R: Serialize + Send + 'static,
380 {
381 Self::request(pattern, move |message: TransportMessage| {
382 let payload = message.data_as::<T>();
383 let future = payload.map(&handler);
384 async move {
385 let response = future?.await?;
386 TransportReply::json(&response)
387 }
388 })
389 }
390
391 pub fn request_validated_json<T, H, Fut, R>(
392 pattern: impl Into<String>,
393 handler: H,
394 ) -> Result<Self>
395 where
396 T: DeserializeOwned + Validate + Send + 'static,
397 H: Fn(T) -> Fut + Send + Sync + 'static,
398 Fut: Future<Output = Result<R>> + Send + 'static,
399 R: Serialize + Send + 'static,
400 {
401 Self::request(pattern, move |message: TransportMessage| {
402 let payload = message.validated_data::<T>();
403 let future = payload.map(&handler);
404 async move {
405 let response = future?.await?;
406 TransportReply::json(&response)
407 }
408 })
409 }
410
411 pub fn event_json<T, H, Fut>(pattern: impl Into<String>, handler: H) -> Result<Self>
412 where
413 T: DeserializeOwned + Send + 'static,
414 H: Fn(T) -> Fut + Send + Sync + 'static,
415 Fut: Future<Output = Result<()>> + Send + 'static,
416 {
417 Self::event(pattern, move |message: TransportMessage| {
418 let payload = message.data_as::<T>();
419 let future = payload.map(&handler);
420 async move { future?.await }
421 })
422 }
423
424 pub fn event_validated_json<T, H, Fut>(pattern: impl Into<String>, handler: H) -> Result<Self>
425 where
426 T: DeserializeOwned + Validate + Send + 'static,
427 H: Fn(T) -> Fut + Send + Sync + 'static,
428 Fut: Future<Output = Result<()>> + Send + 'static,
429 {
430 Self::event(pattern, move |message: TransportMessage| {
431 let payload = message.validated_data::<T>();
432 let future = payload.map(&handler);
433 async move { future?.await }
434 })
435 }
436
437 fn new<H, Fut, R>(
438 pattern: impl Into<String>,
439 kind: MessagePatternKind,
440 handler: H,
441 ) -> Result<Self>
442 where
443 H: Fn(TransportMessage) -> Fut + Send + Sync + 'static,
444 Fut: Future<Output = Result<R>> + Send + 'static,
445 R: IntoTransportReply + Send + 'static,
446 {
447 let pattern = pattern.into();
448 validate_pattern(&pattern)?;
449 Ok(Self {
450 pattern,
451 kind,
452 handler: Arc::new(TransportHandlerAdapter { handler }),
453 pipes: Vec::new(),
454 guards: Vec::new(),
455 interceptors: Vec::new(),
456 validators: Vec::new(),
457 module_name: None,
458 })
459 }
460
461 pub fn pattern(&self) -> &str {
462 &self.pattern
463 }
464
465 pub fn kind(&self) -> MessagePatternKind {
466 self.kind
467 }
468
469 pub fn module_name(&self) -> Option<&str> {
470 self.module_name.as_deref()
471 }
472
473 pub fn with_pipe<P>(mut self, pipe: P) -> Self
474 where
475 P: TransportPipe,
476 {
477 self.pipes.push(Arc::new(pipe));
478 self
479 }
480
481 pub fn with_guard<G>(mut self, guard: G) -> Self
482 where
483 G: TransportGuard,
484 {
485 self.guards.push(Arc::new(guard));
486 self
487 }
488
489 pub fn with_execution_guard<G>(mut self, guard: G) -> Self
490 where
491 G: Guard,
492 {
493 self.guards
494 .push(Arc::new(ExecutionTransportGuard { inner: guard }));
495 self
496 }
497
498 pub(crate) fn with_execution_pipeline_prefix(
499 mut self,
500 guards: &[Arc<dyn Guard>],
501 interceptors: &[Arc<dyn ExecutionInterceptor>],
502 ) -> Self {
503 self.guards = prepend_execution_guards(guards, self.guards);
504 self.interceptors = prepend_execution_interceptors(interceptors, self.interceptors);
505 self
506 }
507
508 pub fn with_interceptor<I>(mut self, interceptor: I) -> Self
509 where
510 I: TransportInterceptor,
511 {
512 self.interceptors.push(Arc::new(interceptor));
513 self
514 }
515
516 pub fn with_execution_interceptor<I>(mut self, interceptor: I) -> Self
517 where
518 I: ExecutionInterceptor,
519 {
520 self.interceptors
521 .push(Arc::new(ExecutionTransportInterceptor {
522 inner: interceptor,
523 }));
524 self
525 }
526
527 pub fn with_payload_validation<T>(mut self) -> Self
528 where
529 T: DeserializeOwned + Validate + 'static,
530 {
531 self.validators.push(Arc::new(|message| {
532 message.validated_data::<T>().map(|_| ())
533 }));
534 self
535 }
536
537 pub async fn dispatch(&self, mut message: TransportMessage) -> Result<Option<TransportReply>> {
538 if message.pattern != self.pattern {
539 return Err(BootError::NotFound(format!(
540 "message pattern {}",
541 message.pattern
542 )));
543 }
544
545 let context = TransportContext::new(self, &message.pattern);
546 for guard in &self.guards {
547 let can_activate = guard.can_activate(context.clone()).await?;
548 if !can_activate {
549 return Err(BootError::Forbidden(format!(
550 "message pattern {}",
551 message.pattern
552 )));
553 }
554 }
555
556 for interceptor in &self.interceptors {
557 interceptor.before(context.clone()).await?;
558 }
559
560 for pipe in &self.pipes {
561 message = pipe.transform(message).await?;
562 }
563
564 for validator in &self.validators {
565 validator(&message)?;
566 }
567
568 let mut reply = self.handler.call(message).await?;
569 if self.kind == MessagePatternKind::Event {
570 reply = None;
571 }
572
573 for interceptor in self.interceptors.iter().rev() {
574 reply = interceptor.after(context.clone(), reply).await?;
575 }
576 Ok(reply)
577 }
578
579 pub(crate) fn with_module_name(mut self, module_name: &str) -> Self {
580 self.module_name = Some(module_name.to_string());
581 self
582 }
583}
584
585fn prepend_execution_guards(
586 prefix: &[Arc<dyn Guard>],
587 values: Vec<Arc<dyn TransportGuard>>,
588) -> Vec<Arc<dyn TransportGuard>> {
589 let mut merged = prefix
590 .iter()
591 .cloned()
592 .map(|guard| Arc::new(ExecutionTransportGuard { inner: guard }) as Arc<dyn TransportGuard>)
593 .collect::<Vec<_>>();
594 merged.extend(values);
595 merged
596}
597
598fn prepend_execution_interceptors(
599 prefix: &[Arc<dyn ExecutionInterceptor>],
600 values: Vec<Arc<dyn TransportInterceptor>>,
601) -> Vec<Arc<dyn TransportInterceptor>> {
602 let mut merged = prefix
603 .iter()
604 .cloned()
605 .map(|interceptor| {
606 Arc::new(ExecutionTransportInterceptor { inner: interceptor })
607 as Arc<dyn TransportInterceptor>
608 })
609 .collect::<Vec<_>>();
610 merged.extend(values);
611 merged
612}
613
614pub trait MessageTransport {
616 type Output;
617
618 fn build(&self, app: crate::BootApplication) -> Result<Self::Output>;
619
620 fn serve(&self, app: crate::BootApplication) -> BoxFuture<'static, Result<()>>;
621}
622
623#[derive(Debug, Clone, Copy, Default)]
625pub struct InProcessTransport;
626
627impl InProcessTransport {
628 pub fn new() -> Self {
629 Self
630 }
631}
632
633impl MessageTransport for InProcessTransport {
634 type Output = InProcessTransportClient;
635
636 fn build(&self, app: crate::BootApplication) -> Result<Self::Output> {
637 Ok(InProcessTransportClient { app })
638 }
639
640 fn serve(&self, _app: crate::BootApplication) -> BoxFuture<'static, Result<()>> {
641 Box::pin(async { Ok(()) })
642 }
643}
644
645#[derive(Clone)]
647pub struct InProcessTransportClient {
648 app: crate::BootApplication,
649}
650
651impl InProcessTransportClient {
652 pub async fn send(&self, message: TransportMessage) -> Result<Option<TransportReply>> {
653 self.app.dispatch_message(message).await
654 }
655
656 pub async fn emit(&self, message: TransportMessage) -> Result<()> {
657 self.app.emit_message(message).await
658 }
659}
660
661fn validate_pattern(pattern: &str) -> Result<()> {
662 if pattern.trim().is_empty() {
663 return Err(BootError::BadRequest(
664 "message pattern cannot be empty".to_string(),
665 ));
666 }
667 Ok(())
668}