use super::identity::{SidecarCapability, SidecarId};
use crate::internal::domain::RequestId;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use time::{Duration, OffsetDateTime};
use uuid::Uuid;
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
pub struct RelaySessionId(String);
impl RelaySessionId {
#[must_use]
pub fn new() -> Self {
Self(format!("relay-{}", Uuid::now_v7()))
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl Default for RelaySessionId {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RelaySession {
pub relay_session_id: RelaySessionId,
pub sidecar_id: SidecarId,
pub remote_instance_id: String,
#[schemars(with = "String")]
#[serde(with = "time::serde::rfc3339")]
pub heartbeat_at: OffsetDateTime,
#[schemars(with = "String")]
#[serde(with = "time::serde::rfc3339")]
pub expires_at: OffsetDateTime,
pub capabilities: Vec<SidecarCapability>,
}
impl RelaySession {
#[must_use]
pub fn is_available(&self, now: OffsetDateTime) -> bool {
self.expires_at > now && self.heartbeat_at <= now
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct ForwardedBrokerRequest {
pub request_id: RequestId,
pub tool_name: String,
pub scope: String,
pub payload_hash: String,
#[schemars(with = "String")]
#[serde(with = "time::serde::rfc3339")]
pub created_at: OffsetDateTime,
}
#[must_use]
pub fn create_relay_session(
sidecar_id: SidecarId,
remote_instance_id: impl Into<String>,
ttl_seconds: i64,
) -> RelaySession {
let now = OffsetDateTime::now_utc();
RelaySession {
relay_session_id: RelaySessionId::new(),
sidecar_id,
remote_instance_id: remote_instance_id.into(),
heartbeat_at: now,
expires_at: now + Duration::seconds(ttl_seconds.max(1)),
capabilities: vec![SidecarCapability::BrokerRead, SidecarCapability::Heartbeat],
}
}