From 40532c9e36443fe38775adadd15b383ec7f17c8d Mon Sep 17 00:00:00 2001 From: snow flurry Date: Mon, 19 Aug 2024 14:04:34 -0700 Subject: [PATCH] events: use JSON instead of Bincode Bincode doesn't support serde's deserialize_any, so it's easier to use JSON for de/serializing events. Since they'll likely be pretty sparse, the size difference shouldn't be a big deal. --- Cargo.lock | 2 +- nzr-api/Cargo.toml | 2 +- nzr-api/src/event/client.rs | 2 +- nzr-api/src/event/mod.rs | 10 +++++---- nzr-api/src/event/server.rs | 6 +++++- nzr-api/src/event/test.rs | 43 +++++++++++++++++++++++++++++++++++++ 6 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 nzr-api/src/event/test.rs diff --git a/Cargo.lock b/Cargo.lock index 1002f5a..ebcd9c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1540,7 +1540,6 @@ dependencies = [ name = "nzr-api" version = "0.1.0" dependencies = [ - "bincode", "diesel", "figment", "futures", @@ -1549,6 +1548,7 @@ dependencies = [ "log", "regex", "serde", + "serde_json", "tarpc", "thiserror", "tokio", diff --git a/nzr-api/Cargo.toml b/nzr-api/Cargo.toml index 302d1f8..292e7c0 100644 --- a/nzr-api/Cargo.toml +++ b/nzr-api/Cargo.toml @@ -23,7 +23,7 @@ regex = "1" lazy_static = "1" tracing = "0.1" tokio-serde = { version = "0.9", features = ["bincode"] } -bincode = "1.3" +serde_json = "1" [dev-dependencies] uuid = { version = "1.2.2", features = ["serde", "v4"] } diff --git a/nzr-api/src/event/client.rs b/nzr-api/src/event/client.rs index feecad3..1c0fb0f 100644 --- a/nzr-api/src/event/client.rs +++ b/nzr-api/src/event/client.rs @@ -41,7 +41,7 @@ where Poll::Ready(res) => { let our_res = res.map(|res| { res.map_err(|e| e.into()).and_then(|bytes| { - let msg: EventMessage = bincode::deserialize(&bytes)?; + let msg: EventMessage = serde_json::from_slice(&bytes)?; Ok(msg) }) }); diff --git a/nzr-api/src/event/mod.rs b/nzr-api/src/event/mod.rs index 1b6ee7b..48479bc 100644 --- a/nzr-api/src/event/mod.rs +++ b/nzr-api/src/event/mod.rs @@ -1,5 +1,7 @@ pub mod client; pub mod server; +#[cfg(test)] +mod test; use std::io; @@ -8,7 +10,7 @@ use thiserror::Error; use crate::model; -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub enum ResourceAction { /// The referenced resource was created. Created, @@ -19,7 +21,7 @@ pub enum ResourceAction { } /// Represents an event pertaining to a specific action. -#[derive(Clone, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct ResourceEvent { pub action: ResourceAction, /// The entity that was acted upon. @@ -27,7 +29,7 @@ pub struct ResourceEvent { } /// Represents any event that is emitted by Nazrin. -#[derive(Clone, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] #[serde(tag = "event")] pub enum EventMessage { /// A subnet was created, modified, or deleted. @@ -41,7 +43,7 @@ pub enum EventError { #[error("Transport error: {0}")] Transport(#[from] io::Error), #[error("Serialization error: {0}")] - Bincode(#[from] bincode::Error), + Json(#[from] serde_json::Error), } pub trait Emittable { diff --git a/nzr-api/src/event/server.rs b/nzr-api/src/event/server.rs index f790d95..8db504b 100644 --- a/nzr-api/src/event/server.rs +++ b/nzr-api/src/event/server.rs @@ -20,6 +20,8 @@ pub enum SocketAddr { #[cfg(unix)] Unix(std::os::unix::net::SocketAddr), Net(std::net::SocketAddr), + #[cfg(test)] + None, } impl fmt::Display for SocketAddr { @@ -30,6 +32,8 @@ impl fmt::Display for SocketAddr { #[cfg(unix)] Self::Unix(addr) => std::fmt::Debug::fmt(addr, f), Self::Net(addr) => addr.fmt(f), + #[cfg(test)] + Self::None => write!(f, "mock client"), } } } @@ -145,7 +149,7 @@ impl EventServer { /// Send the given event to all connected clients. pub async fn emit(&self, msg: EventMessage) { - let bytes = match bincode::serialize(&msg) { + let bytes = match serde_json::to_vec(&msg) { Ok(bytes) => bytes, Err(err) => { tracing::error!("Failed to serialize: {err}"); diff --git a/nzr-api/src/event/test.rs b/nzr-api/src/event/test.rs new file mode 100644 index 0000000..14416d3 --- /dev/null +++ b/nzr-api/src/event/test.rs @@ -0,0 +1,43 @@ +use std::str::FromStr; + +use futures::StreamExt; + +use crate::{ + event::{server::SocketAddr, EventMessage, ResourceAction}, + net::cidr::CidrV4, + nzr_event, +}; + +#[tokio::test] +async fn event_serde() { + let (rx, tx) = tokio::io::duplex(1024); + let server = super::server::EventServer::default(); + server.spawn(tx, SocketAddr::None).await.unwrap(); + let mut client = super::client::EventClient::new(rx); + let net = CidrV4::from_str("192.0.2.0/24").unwrap(); + let some_subnet = crate::model::Subnet { + name: "whatever".into(), + data: crate::model::SubnetData { + ifname: "eth0".into(), + network: net, + start_host: net.make_ip(10).unwrap(), + end_host: net.make_ip(254).unwrap(), + gateway4: Some(net.make_ip(1).unwrap()), + dns: Vec::new(), + domain_name: Some("homestarrunnner.net".parse().unwrap()), + vlan_id: None, + }, + }; + nzr_event!(server, Created, some_subnet); + let next = client + .next() + .await + .expect("client must receive message") + .unwrap(); + + let EventMessage::Subnet(net) = next else { + panic!("Unexpected event received: {next:?}"); + }; + + assert_eq!(net.action, ResourceAction::Created); +}