use anyhow::Result;
use async_trait::async_trait;
use futures::stream::BoxStream;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct RoomMemberSnapshot {
#[serde(rename = "nodeId")]
pub node_id: String,
#[serde(rename = "userId")]
pub user_id: String,
pub ticket: String,
#[serde(rename = "joinedAt")]
pub joined_at: i64,
#[serde(rename = "lastSeenAt")]
pub last_seen_at: i64,
#[serde(rename = "expiresAt", skip_serializing_if = "Option::is_none")]
pub expires_at: Option<i64>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum RoomMemberEvent {
Modified {
member: RoomMemberSnapshot,
},
Removed {
#[serde(rename = "memberId")]
member_id: String,
},
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait RoomBackend: crate::signaling::SendSyncBound {
async fn create_room(
&self,
room_id: &str,
user_id: &str,
ticket_str: &str,
my_node_id: &str,
app_tag: &str,
max_members: Option<u32>,
) -> Result<bool>;
async fn get_members(
&self,
room_id: &str,
my_node_id: &str,
app_tag: &str,
) -> Result<Vec<RoomMemberSnapshot>>;
async fn join_room(
&self,
room_id: &str,
user_id: &str,
ticket_str: &str,
my_node_id: &str,
app_tag: &str,
) -> Result<()>;
async fn leave_room(&self, room_id: &str, my_node_id: &str, app_tag: &str) -> Result<()>;
async fn heartbeat_tick(&self, room_id: &str, member_id: &str, app_tag: &str) -> Result<()>;
async fn subscribe_members(
&self,
room_id: &str,
my_node_id: &str,
app_tag: &str,
) -> Result<BoxStream<'static, Result<Vec<RoomMemberEvent>>>>;
}
#[derive(Debug, Default)]
pub struct GatewayRequiredRoomBackend;
impl GatewayRequiredRoomBackend {
fn unavailable<T>() -> Result<T> {
anyhow::bail!(
"managed room coordination gateway is required; direct provider rooms have been removed"
)
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl RoomBackend for GatewayRequiredRoomBackend {
async fn create_room(
&self,
_room_id: &str,
_user_id: &str,
_ticket_str: &str,
_my_node_id: &str,
_app_tag: &str,
_max_members: Option<u32>,
) -> Result<bool> {
Self::unavailable()
}
async fn get_members(
&self,
_room_id: &str,
_my_node_id: &str,
_app_tag: &str,
) -> Result<Vec<RoomMemberSnapshot>> {
Self::unavailable()
}
async fn join_room(
&self,
_room_id: &str,
_user_id: &str,
_ticket_str: &str,
_my_node_id: &str,
_app_tag: &str,
) -> Result<()> {
Self::unavailable()
}
async fn leave_room(&self, _room_id: &str, _my_node_id: &str, _app_tag: &str) -> Result<()> {
Self::unavailable()
}
async fn heartbeat_tick(&self, _room_id: &str, _member_id: &str, _app_tag: &str) -> Result<()> {
Self::unavailable()
}
async fn subscribe_members(
&self,
_room_id: &str,
_my_node_id: &str,
_app_tag: &str,
) -> Result<BoxStream<'static, Result<Vec<RoomMemberEvent>>>> {
Self::unavailable()
}
}