Skip to main content

allora_runtime/spec/
http_outbound_adapter_spec.rs

1use serde::Deserialize;
2
3#[derive(Debug, Clone, Deserialize)]
4pub struct HttpOutboundAdapterSpecRootV1 {
5    pub version: u32,
6    #[serde(rename = "http-outbound-adapter")]
7    pub http_outbound_adapter: HttpOutboundAdapterSpecBlock,
8}
9
10#[derive(Debug, Clone, Deserialize)]
11pub struct HttpOutboundAdapterSpecBlock {
12    pub id: Option<String>,
13    /// Full target URL (must include scheme — `http://` or `https://`).
14    ///
15    /// Replaces the legacy `host` + `port` + `base-path` triple as of
16    /// 0.0.9. Parsing happens in the YAML parser; invalid URLs surface
17    /// as `Error::Serialization` rather than panicking at dispatch time.
18    pub url: String,
19    pub method: Option<String>,
20    #[serde(rename = "use-out-msg")]
21    pub use_out_msg: Option<bool>,
22    /// Channel-driven dispatch: when present, the runtime subscribes this
23    /// adapter to the named inbound channel and dispatches each arriving
24    /// exchange. When absent, the adapter is built but not auto-wired —
25    /// application code can still invoke `.dispatch(&exchange)` directly
26    /// (the legacy http-outbound example pattern).
27    pub from: Option<String>,
28    /// Outbound channel for the post-dispatch exchange. Ignored when
29    /// `from` is absent. When `from` is set but `to` is `None`, the
30    /// adapter is fire-and-forget: dispatch happens, the result is
31    /// logged, the message is dropped.
32    pub to: Option<String>,
33}
34
35#[derive(Debug, Clone)]
36pub struct HttpOutboundAdapterSpec(HttpOutboundAdapterSpecBlock);
37
38impl HttpOutboundAdapterSpec {
39    pub(crate) fn from_block(b: HttpOutboundAdapterSpecBlock) -> Self {
40        Self(b)
41    }
42    /// Programmatic constructor.
43    ///
44    /// `url` must include the scheme (`http://` or `https://`). It is not
45    /// validated here — validation happens when the spec is constructed
46    /// via the YAML parser, or when the adapter is built. Callers using
47    /// this constructor directly are expected to provide a parseable URL.
48    pub fn new(url: &str, method: Option<&str>, id: Option<&str>, use_out_msg: bool) -> Self {
49        let blk = HttpOutboundAdapterSpecBlock {
50            id: id.map(|s| s.to_string()),
51            url: url.to_string(),
52            method: method.map(|m| m.to_string()),
53            use_out_msg: Some(use_out_msg),
54            from: None,
55            to: None,
56        };
57        Self(blk)
58    }
59    /// Set the inbound channel name the runtime will subscribe this
60    /// adapter to. Returns `self` for chaining; intended for fluent test
61    /// fixture construction.
62    pub fn with_from(mut self, from: impl Into<String>) -> Self {
63        self.0.from = Some(from.into());
64        self
65    }
66    /// Set the outbound channel name for the post-dispatch exchange.
67    pub fn with_to(mut self, to: impl Into<String>) -> Self {
68        self.0.to = Some(to.into());
69        self
70    }
71    pub fn with_id(id: &str, url: &str, method: Option<&str>, use_out_msg: bool) -> Self {
72        Self::new(url, method, Some(id), use_out_msg)
73    }
74    pub fn id(&self) -> Option<&str> {
75        self.0.id.as_deref()
76    }
77    /// Target URL as configured (raw string). Includes scheme.
78    pub fn url(&self) -> &str {
79        &self.0.url
80    }
81    pub fn method(&self) -> Option<&str> {
82        self.0.method.as_deref()
83    }
84    pub fn use_out_msg(&self) -> bool {
85        self.0.use_out_msg.unwrap_or(true)
86    }
87    /// Inbound channel name for channel-driven dispatch, if set.
88    pub fn from(&self) -> Option<&str> {
89        self.0.from.as_deref()
90    }
91    /// Outbound channel name for the post-dispatch exchange, if set.
92    pub fn to(&self) -> Option<&str> {
93        self.0.to.as_deref()
94    }
95}