kumo_api_types/
xfer.rs

1use serde::{Deserialize, Serialize};
2use url::Url;
3use utoipa::{ToResponse, ToSchema};
4
5#[derive(Deserialize, Serialize, Debug, Clone, ToSchema)]
6pub struct XferProtocol {
7    /// Expected to be an HTTP url prefix like:
8    /// `https://host.name:8008`
9    /// `http://127.0.0.1:8000`
10    // TODO: support multiple, as well as resolving the hostname
11    // to multiple candidates so that we can immediately retry
12    // transient issues on subsequent candidates
13    pub target: Url,
14}
15
16const XFER_QUEUE_SUFFIX: &str = ".xfer.kumomta.internal";
17
18impl XferProtocol {
19    pub fn is_xfer_queue_name(name: &str) -> bool {
20        name.ends_with(XFER_QUEUE_SUFFIX)
21    }
22
23    pub fn to_queue_name(&self) -> String {
24        format!("{}{XFER_QUEUE_SUFFIX}", self.target)
25    }
26
27    pub fn from_queue_name(name: &str) -> Option<Self> {
28        let name = name.strip_suffix(XFER_QUEUE_SUFFIX)?;
29        let target: Url = name.parse().ok()?;
30        Some(Self { target })
31    }
32}
33
34/// Describes which messages should be transferred to another
35/// kumomta node.
36/// The criteria apply to the scheduled queue associated
37/// with a given message.
38#[derive(Serialize, Deserialize, Debug, ToSchema)]
39pub struct XferV1Request {
40    /// The campaign name to match. If omitted, any campaign will match.
41    #[serde(default)]
42    pub campaign: Option<String>,
43
44    /// The tenant to match. If omitted, any tenant will match.
45    #[serde(default)]
46    pub tenant: Option<String>,
47
48    /// The domain name to match. If omitted, any domain will match.
49    #[serde(default)]
50    #[schema(example = "example.com")]
51    pub domain: Option<String>,
52
53    /// The routing_domain name to match. If omitted, any routing_domain will match.
54    #[serde(default)]
55    pub routing_domain: Option<String>,
56
57    /// Reason to log in the delivery log. Each matching message will log
58    /// with an AdminRebind record to indicate that it was moved from
59    /// its containing queue, and this reason will be included in that record.
60    #[schema(example = "Scaling down")]
61    pub reason: String,
62
63    /// If present, queue_names takes precedence over `campaign`,
64    /// `tenant`, and `domain` and specifies the exact set of
65    /// scheduled queue names to which the xfer applies.
66    #[serde(default, skip_serializing_if = "Vec::is_empty")]
67    pub queue_names: Vec<String>,
68
69    #[serde(flatten)]
70    pub protocol: XferProtocol,
71}
72
73#[derive(Serialize, Deserialize, Debug, ToSchema, ToResponse)]
74pub struct XferV1Response {}
75
76#[derive(Serialize, Deserialize, Debug, ToSchema)]
77pub struct XferCancelV1Request {
78    /// The name of the xfer scheduled queue
79    pub queue_name: String,
80
81    /// Reason to log in the delivery log. Each matching message will log
82    /// with an AdminRebind record to indicate that it was moved from
83    /// its containing queue, and this reason will be included in that record.
84    #[schema(example = "Scaling down")]
85    pub reason: String,
86}
87
88#[derive(Serialize, Deserialize, Debug, ToSchema, ToResponse)]
89pub struct XferCancelV1Response {}