use std::sync::atomic::{AtomicU64, Ordering};
use std::time::Duration;
use core_api::{ServiceRequestId, UdpServiceClient, UdpServiceIncoming, UdpServiceServer};
use introspection_core::StatusSnapshot;
use serde::{Deserialize, Serialize};
pub const STATUS_SERVICE_API_VERSION: &str = "robotrt.status.service.v1";
pub const STATUS_SERVICE_NAME: &str = "/robotrt/status/query";
pub const NODE_INFO_API_VERSION: &str = "robotrt.node.info.v1";
pub const TOPIC_INFO_API_VERSION: &str = "robotrt.topic.info.v1";
pub const ACTION_INFO_API_VERSION: &str = "robotrt.action.info.v1";
static NEXT_STATUS_REQUEST_ID: AtomicU64 = AtomicU64::new(1);
#[derive(Debug, Serialize, Deserialize)]
pub struct StatusServiceRequest {
pub api_version: String,
pub op: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct StatusServiceResponse {
pub api_version: String,
pub snapshot: StatusSnapshot,
}
pub fn next_request_id() -> ServiceRequestId {
ServiceRequestId(NEXT_STATUS_REQUEST_ID.fetch_add(1, Ordering::Relaxed))
}
pub fn build_snapshot_request(_request_id: ServiceRequestId) -> StatusServiceRequest {
StatusServiceRequest {
api_version: STATUS_SERVICE_API_VERSION.to_string(),
op: "snapshot".to_string(),
}
}
pub fn validate_request(req: &StatusServiceRequest) -> Result<(), String> {
if req.api_version != STATUS_SERVICE_API_VERSION {
return Err(format!(
"unsupported api_version={} expected={}",
req.api_version, STATUS_SERVICE_API_VERSION
));
}
if req.op != "snapshot" {
return Err(format!("unsupported op={}", req.op));
}
Ok(())
}
pub fn success_response(
_request_id: ServiceRequestId,
snapshot: StatusSnapshot,
) -> StatusServiceResponse {
StatusServiceResponse {
api_version: STATUS_SERVICE_API_VERSION.to_string(),
snapshot,
}
}
pub fn validate_response(
resp: &StatusServiceResponse,
_request_id: ServiceRequestId,
) -> Result<(), String> {
if resp.api_version != STATUS_SERVICE_API_VERSION {
return Err(format!(
"unsupported response api_version={} expected={}",
resp.api_version, STATUS_SERVICE_API_VERSION
));
}
Ok(())
}
pub fn make_udp_service_client(
endpoint: String,
timeout_ms: u64,
) -> Result<UdpServiceClient, String> {
UdpServiceClient::new(endpoint, Duration::from_millis(timeout_ms))
.map_err(|err| format!("create udp service client failed: {err}"))
}
pub fn make_udp_service_server(bind: &str) -> Result<UdpServiceServer, String> {
UdpServiceServer::bind(bind).map_err(|err| format!("bind udp service server failed: {err}"))
}
pub fn recv_status_request(
server: &UdpServiceServer,
) -> Result<UdpServiceIncoming<StatusServiceRequest>, String> {
server
.recv_json::<StatusServiceRequest>()
.map_err(|err| format!("recv status service request failed: {err}"))
}