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 target: RouteTarget,
51 identity: BindIdentity,
52 #[serde(default, skip_serializing_if = "Option::is_none")]
53 principal: Option<Principal>,
54 #[serde(default, skip_serializing_if = "Option::is_none")]
62 consumer_capabilities: Option<Vec<String>>,
63 },
64 #[serde(rename = "health.check")]
65 HealthCheck {},
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
70#[serde(tag = "op")]
71pub enum ModuleControlResponse {
72 #[serde(rename = "route.bind")]
74 RouteBindAck {},
75 #[serde(rename = "health.check")]
76 HealthCheck {
77 status: HealthStatus,
78 #[serde(default, skip_serializing_if = "Option::is_none")]
79 detail: Option<String>,
80 #[serde(default, skip_serializing_if = "Option::is_none")]
81 metrics: Option<Value>,
82 },
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
91#[serde(tag = "op")]
92pub enum ModuleControlRequestFromModule {
93 #[serde(rename = "catalog.update")]
94 CatalogUpdate { provides: Vec<ProviderRole> },
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
99#[serde(tag = "op")]
100pub enum ModuleControlResponseToModule {
101 #[serde(rename = "catalog.update")]
102 CatalogUpdate {},
103}
104
105impl From<HealthReport> for ModuleControlResponse {
106 fn from(report: HealthReport) -> Self {
107 Self::HealthCheck {
108 status: report.status,
109 detail: report.detail,
110 metrics: report.metrics,
111 }
112 }
113}
114
115impl ModuleControlResponse {
116 pub fn health_report(&self) -> Option<HealthReport> {
117 match self {
118 Self::HealthCheck {
119 status,
120 detail,
121 metrics,
122 } => Some(HealthReport {
123 status: *status,
124 detail: detail.clone(),
125 metrics: metrics.clone(),
126 }),
127 Self::RouteBindAck {} => None,
128 }
129 }
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
134#[serde(tag = "op")]
135pub enum ModuleControlPush {
136 #[serde(rename = "route.status")]
137 RouteStatus { route_channel: u16, status: String },
138}