1use serde::{Deserialize, Serialize};
9use serde_json::Value;
10
11use crate::{manifest::ProviderRole, BindIdentity, Principal, RouteTarget};
12
13pub const MODULE_CONTROL_OP_HEALTH_CHECK: &str = "health.check";
14pub const MODULE_TO_SUBC_OP_CATALOG_UPDATE: &str = "catalog.update";
15
16#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
17#[serde(rename_all = "snake_case")]
18pub enum HealthStatus {
19 Ok,
20 Degraded,
21 Failing,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
25pub struct HealthReport {
26 pub status: HealthStatus,
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 pub detail: Option<String>,
29 #[serde(default, skip_serializing_if = "Option::is_none")]
30 pub metrics: Option<Value>,
31}
32
33impl HealthReport {
34 pub fn ok() -> Self {
35 Self {
36 status: HealthStatus::Ok,
37 detail: None,
38 metrics: None,
39 }
40 }
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
45#[serde(tag = "op")]
46pub enum ModuleControlRequest {
47 #[serde(rename = "route.bind")]
48 RouteBind {
49 route_channel: u16,
50 epoch: u32,
51 target: RouteTarget,
52 identity: BindIdentity,
53 #[serde(default, skip_serializing_if = "Option::is_none")]
54 principal: Option<Principal>,
55 #[serde(default, skip_serializing_if = "Option::is_none")]
63 consumer_capabilities: Option<Vec<String>>,
64 },
65 #[serde(rename = "health.check")]
66 HealthCheck {},
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
71#[serde(tag = "op")]
72pub enum ModuleControlResponse {
73 #[serde(rename = "route.bind")]
75 RouteBindAck {},
76 #[serde(rename = "health.check")]
77 HealthCheck {
78 status: HealthStatus,
79 #[serde(default, skip_serializing_if = "Option::is_none")]
80 detail: Option<String>,
81 #[serde(default, skip_serializing_if = "Option::is_none")]
82 metrics: Option<Value>,
83 },
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
92#[serde(tag = "op")]
93pub enum ModuleControlRequestFromModule {
94 #[serde(rename = "catalog.update")]
95 CatalogUpdate { provides: Vec<ProviderRole> },
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
100#[serde(tag = "op")]
101pub enum ModuleControlResponseToModule {
102 #[serde(rename = "catalog.update")]
103 CatalogUpdate {},
104}
105
106impl From<HealthReport> for ModuleControlResponse {
107 fn from(report: HealthReport) -> Self {
108 Self::HealthCheck {
109 status: report.status,
110 detail: report.detail,
111 metrics: report.metrics,
112 }
113 }
114}
115
116impl ModuleControlResponse {
117 pub fn health_report(&self) -> Option<HealthReport> {
118 match self {
119 Self::HealthCheck {
120 status,
121 detail,
122 metrics,
123 } => Some(HealthReport {
124 status: *status,
125 detail: detail.clone(),
126 metrics: metrics.clone(),
127 }),
128 Self::RouteBindAck {} => None,
129 }
130 }
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
135#[serde(tag = "op")]
136pub enum ModuleControlPush {
137 #[serde(rename = "route.status")]
138 RouteStatus {
139 route_channel: u16,
140 route_epoch: u32,
141 status: String,
142 },
143}