use codemp_proto::{ buffer::buffer_client::BufferClient, common::Token, cursor::cursor_client::CursorClient, workspace::workspace_client::WorkspaceClient, }; use tonic::{ service::{interceptor::InterceptedService, Interceptor}, transport::{Channel, Endpoint}, }; use crate::errors::ConnectionResult; type AuthedService = InterceptedService; #[derive(Debug, Clone)] pub struct SessionInterceptor(pub tokio::sync::watch::Receiver); impl tonic::service::Interceptor for SessionInterceptor { fn call(&mut self, mut request: tonic::Request<()>) -> tonic::Result> { if let Ok(token) = self.0.borrow().token.parse() { request.metadata_mut().insert("session", token); } Ok(request) } } #[derive(Debug)] pub struct Services { workspace: WorkspaceClient, buffer: BufferClient, cursor: CursorClient, } impl Services { pub async fn try_new( dest: &str, session: tokio::sync::watch::Receiver, workspace: tokio::sync::watch::Receiver, ) -> ConnectionResult { // TRANSPORT ERROR let channel = Endpoint::from_shared(dest.to_string())?.connect().await?; let inter = WorkspaceInterceptor { session, workspace }; Ok(Self { cursor: CursorClient::with_interceptor(channel.clone(), inter.clone()), workspace: WorkspaceClient::with_interceptor(channel.clone(), inter.clone()), // TODO technically we could keep buffers on separate servers, and thus manage buffer // connections separately, but for now it's more convenient to bundle them with workspace buffer: BufferClient::with_interceptor(channel.clone(), inter.clone()), }) } // TODO just make fields pub(crate) ?? idk pub fn ws(&self) -> WorkspaceClient { self.workspace.clone() } pub fn buf(&self) -> BufferClient { self.buffer.clone() } pub fn cur(&self) -> CursorClient { self.cursor.clone() } } #[derive(Clone)] pub struct WorkspaceInterceptor { session: tokio::sync::watch::Receiver, workspace: tokio::sync::watch::Receiver, } impl Interceptor for WorkspaceInterceptor { fn call( &mut self, mut request: tonic::Request<()>, ) -> Result, tonic::Status> { if let Ok(token) = self.session.borrow().token.parse() { request.metadata_mut().insert("session", token); } if let Ok(token) = self.workspace.borrow().token.parse() { request.metadata_mut().insert("workspace", token); } Ok(request) } }