Skip to main content

wowlab_common/
node_realtime.rs

1//! Realtime messages shared by simulation nodes and Sentinel.
2
3use serde::{Deserialize, Serialize};
4
5/// Message published on a node's `nodes:{public_key}` realtime channel.
6#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
7#[serde(
8    tag = "type",
9    content = "payload",
10    rename_all = "snake_case",
11    rename_all_fields = "camelCase"
12)]
13#[non_exhaustive]
14pub enum NodeRealtimeMessage {
15    ConfigurationUpdated {
16        name: String,
17        total_cores: i32,
18        max_parallel: i32,
19    },
20    RefinementUpdated {
21        ids: Vec<Box<str>>,
22    },
23}
24
25#[cfg(test)]
26mod tests {
27    use googletest::prelude::*;
28
29    use super::*;
30
31    #[gtest]
32    fn configuration_updated_uses_the_canonical_wire_shape() -> Result<()> {
33        let message = NodeRealtimeMessage::ConfigurationUpdated {
34            name: "Worker One".to_string(),
35            total_cores: 16,
36            max_parallel: 8,
37        };
38
39        let value = serde_json::to_value(message).or_fail()?;
40
41        verify_that!(
42            value,
43            eq(&serde_json::json!({
44                "type": "configuration_updated",
45                "payload": {
46                    "name": "Worker One",
47                    "totalCores": 16,
48                    "maxParallel": 8
49                }
50            }))
51        )
52    }
53
54    #[gtest]
55    fn refinement_updated_uses_the_canonical_wire_shape() -> Result<()> {
56        let message = NodeRealtimeMessage::RefinementUpdated {
57            ids: vec!["node-public-key".into()],
58        };
59
60        let value = serde_json::to_value(message).or_fail()?;
61
62        verify_that!(
63            value,
64            eq(&serde_json::json!({
65                "type": "refinement_updated",
66                "payload": { "ids": ["node-public-key"] }
67            }))
68        )
69    }
70
71    #[gtest]
72    fn rejects_legacy_and_incomplete_messages() -> Result<()> {
73        let legacy_configuration =
74            br#"{ "name": "Worker One", "totalCores": 16, "maxParallel": 8 }"#;
75        let ambiguous_updated =
76            br#"{ "type": "updated", "payload": { "ids": ["node-public-key"] } }"#;
77        let incomplete_configuration = br#"{
78            "type": "configuration_updated",
79            "payload": { "name": "Worker One" }
80        }"#;
81
82        verify_that!(
83            serde_json::from_slice::<NodeRealtimeMessage>(legacy_configuration),
84            err(anything())
85        )?;
86        verify_that!(
87            serde_json::from_slice::<NodeRealtimeMessage>(ambiguous_updated),
88            err(anything())
89        )?;
90
91        verify_that!(
92            serde_json::from_slice::<NodeRealtimeMessage>(incomplete_configuration),
93            err(anything())
94        )
95    }
96}