1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//! Adapter abstractions: unify how external systems (inbound) and outbound endpoints
//! integrate with Allora's `Exchange` / `Message` pipeline.
//!
//! # Overview
//! * [`Adapter`]: Marker trait implemented by all adapter types (inbound or outbound).
//! * [`InboundAdapter`]: Lifecycle-driven receiver of external stimuli (HTTP server, queue consumer).
//! * [`OutboundAdapter`]: Dispatcher of an `Exchange` toward an external system (HTTP client, producer).
//! * [`ensure_correlation`]: Helper guaranteeing a `correlation_id` header on the inbound `Message`.
//!
//! # Goals
//! * Provide a small, stable surface for decorating adapters (tracing, metrics, auth).
//! * Separate inbound (long-running run loop) from outbound (per-dispatch) semantics.
//! * Encourage early correlation id creation for downstream EIP patterns.
//!
//! # Inbound Example
//! ```
//! use allora_core::{adapter::InboundAdapter, Result};
//! use async_trait::async_trait;
//! #[derive(Debug)]
//! struct StubInbound;
//! impl allora_core::adapter::BaseAdapter for StubInbound { fn id(&self) -> &str { "stub_inbound" } }
//! #[async_trait]
//! impl InboundAdapter for StubInbound {
//! async fn run(&self) -> Result<()> { Ok(()) }
//! }
//! let stub = StubInbound;
//! // Async usage only; no feature gating.
//! tokio::runtime::Runtime::new().unwrap().block_on(async { stub.run().await.unwrap(); });
//! ```
//!
//! # Outbound Example (Hypothetical)
//! ```
//! use allora_core::{adapter::{OutboundAdapter , OutboundDispatchResult}, error::Result, Exchange, Message};
//! use async_trait::async_trait;
//! #[derive(Debug)] struct LoggingOutbound;
//! impl allora_core::adapter::BaseAdapter for LoggingOutbound { fn id(&self) -> &str { "logging_outbound" } }
//! #[async_trait]
//! impl OutboundAdapter for LoggingOutbound {
//! async fn dispatch(&self, exchange: &Exchange) -> Result<OutboundDispatchResult> {
//! Ok(OutboundDispatchResult {
//! acknowledged: true,
//! message: exchange
//! .out_msg
//! .as_ref()
//! .and_then(|m| m.body_text())
//! .map(|s| format!("echo:{s}")),
//! status_code: None,
//! body: None,
//! })
//! }
//! }
//! let adapter = LoggingOutbound;
//! let mut exchange = Exchange::new(Message::from_text("hello"));
//! exchange.out_msg = Some(Message::from_text("world"));
//! // Async usage only; no feature gating.
//! let res = tokio::runtime::Runtime::new().unwrap().block_on(async { adapter.dispatch(&exchange).await.unwrap() });
//! {
//! assert!(res.acknowledged);
//! assert_eq!(res.message.unwrap(), "echo:world");
//! }
//! ```
//!
//! # Correlation Example
//! ```rust
//! use allora_core::{adapter::ensure_correlation, Message, Exchange};
//! let mut exchange = Exchange::new(Message::from_text("payload"));
//! ensure_correlation(&mut exchange);
//! assert!(exchange.in_msg.header("correlation_id").is_some());
//! ```
//!
//! # Correlation Strategy
//! Correlation IDs are lazily generated by [`Exchange::correlation_id`]. Inbound adapters should
//! call [`ensure_correlation`] immediately after constructing the `Exchange` to guarantee downstream
//! processors (aggregators, splitters, request/reply) can rely on the header.
//!
//! # Future Extensions
//! * Middleware chain for adapters (auth, rate limiting).
//! * Backpressure signaling (rejecting inbound requests under load).
//! * Retry / circuit breaker policies for outbound dispatch.
//! * Unified metrics façade (requests_total, dispatch_latency_seconds).
use crate::;
use async_trait;
use Debug;
/// Marker trait for all adapters (inbound or outbound). Intentionally empty so it can be
/// used for blanket implementations of decoration layers. Do NOT add methods here unless they
/// apply uniformly to both inbound and outbound adapters.
/// Inbound adapter: receives external data/events and produces `Exchange`s routed inside Allora.
///
/// Implementations should:
/// * Parse / normalize an external protocol entity into a `Message` (payload + headers).
/// * Invoke [`crate::adapter::ensure_correlation`] before dispatch.
/// * Dispatch the `Exchange` via a channel / route.
/// * Manage lifecycle (bind ports, subscribe to topics, handle shutdown).
/// Metadata returned from outbound dispatch. Leave fields optional / expandable for future.
/// Outbound adapter: sends data derived from an `Exchange` to an external system.
///
/// Implementations should:
/// * Select `in_msg` or `out_msg` as the source for serialization (document behavior).
/// * Propagate correlation / message ids outward if relevant (tracing continuity).
/// * Map remote responses (status, id) back into the returned `OutboundDispatchResult`.
/// Ensure a `correlation_id` header exists on the inbound message of the provided `Exchange`.
/// Safe to call multiple times (id will be stable after first generation).
/// Staged builder root: pattern-first entry (`Adapter::inbound().http()...`).
;
;
;