use anyhow::Result;
use serde::{Deserialize, Serialize};
use velo_ext::PeerInfo;
use crate::messenger::handlers::{Handler, HandlerManager, TypedContext};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HelloRequest {
pub peer_info: PeerInfo,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HandlersResponse {
pub handlers: Vec<String>,
}
fn create_hello_handler() -> Handler {
Handler::typed_unary_async("_hello", |ctx: TypedContext<HelloRequest>| async move {
let peer_info = ctx.input.peer_info;
tracing::debug!(
target: "crate::messenger::system",
instance_id = %peer_info.instance_id(),
"Received _hello handshake from peer"
);
ctx.msg.register_peer(peer_info.clone())?;
let handlers = ctx.msg.list_local_handlers();
tracing::debug!(
target: "crate::messenger::system",
instance_id = %peer_info.instance_id(),
handler_count = handlers.len(),
"Completed _hello handshake"
);
Ok(HandlersResponse { handlers })
})
.spawn()
.build()
}
fn create_list_handlers_handler() -> Handler {
Handler::typed_unary_async("_list_handlers", |ctx: TypedContext<()>| async move {
let handlers = ctx.msg.list_local_handlers();
tracing::debug!(
target: "crate::messenger::system",
handler_count = handlers.len(),
"Responding to _list_handlers query"
);
Ok(HandlersResponse { handlers })
})
.spawn()
.build()
}
pub(crate) fn register_system_handlers(manager: &HandlerManager) -> Result<()> {
manager.register_internal_handler(create_hello_handler())?;
manager.register_internal_handler(create_list_handlers_handler())?;
tracing::info!(
target: "crate::messenger::system",
"Registered system handlers: _hello, _list_handlers"
);
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
fn make_empty_test_address() -> velo_ext::WorkerAddress {
let map: HashMap<String, Vec<u8>> = HashMap::new();
let encoded = rmp_serde::to_vec(&map).unwrap();
velo_ext::WorkerAddress::from_encoded(encoded)
}
#[test]
fn test_hello_request_serialization() {
use velo_ext::InstanceId;
let instance_id = InstanceId::new_v4();
let address = make_empty_test_address();
let peer_info = PeerInfo::new(instance_id, address);
let request = HelloRequest {
peer_info: peer_info.clone(),
};
let json = serde_json::to_string(&request).unwrap();
let deserialized: HelloRequest = serde_json::from_str(&json).unwrap();
assert_eq!(
request.peer_info.instance_id(),
deserialized.peer_info.instance_id()
);
}
#[test]
fn test_handlers_response_serialization() {
let response = HandlersResponse {
handlers: vec![
"handler1".to_string(),
"handler2".to_string(),
"_system".to_string(),
],
};
let json = serde_json::to_string(&response).unwrap();
let deserialized: HandlersResponse = serde_json::from_str(&json).unwrap();
assert_eq!(response.handlers.len(), deserialized.handlers.len());
assert_eq!(response.handlers, deserialized.handlers);
}
}