Closed ilslv closed 2 years ago
@tyranron user-facing API will consist of 3 different traits:
ControlApi
#[async_trait]
pub trait ControlApi<OnJoin, OnLeave> {
// ^^^^^^ Could be `GrpcCallbackUrl`, `HttpCallbackUrl` or anything else.
async fn create_room(
&self,
spec: Room<OnJoin, OnLeave>,
) -> Result<Sids, ErrorResponse>;
// ...
}
Implementor of this trait will be provided to the user, so they could control the media server.
CallbackClientFactory
pub trait CallbackClientFactory<OnJoin, OnLeave> {
fn build(
&self,
url: Either<OnJoin, OnLeave>,
) -> LocalBoxFuture<'static, CallbackResult<Arc<dyn CallbackClient>>>;
}
Implementor of this trait will be provided by user, so media server could communicate back. Also it takes &self
as an argument to be able to store additional context. Without this the only way to communicate between media server and consumer of the ControlApi
would be OnJoin
and OnLeave
generics. But current implementation imposes additional bounds like Eq
, Hash
and Clone
, as they are stored in the HashMap
, which isn't ideal for the shared context.
CallbackClient
#[async_trait(?Send)]
pub trait CallbackClient {
async fn send(&self, request: CallbackRequest) -> CallbackResult;
}
This trait is just a result of the CallbackClientFactory::build
to share events.
Main idea behind splitting CallbackClientFactory
and CallbackClient
is that CallbackClientFactory::build
is called once per connected user (ignoring the reconnection stuff). So with grpc
feature frontend client connects to the ClientApi
of the media server, CallbackClientFactory::build
creates grpc
connection between control and media servers and only then CallbackClient::send
is called on that connection for each event of the corresponding user. This is how current implementation works in Medea
, but hardcoded with GrpcCallbackFactory
and CallbackClientFactory::build
doesn't receive &self
.
All in all, the final setup for Medea
with grpc
control server should look something like that:
MedeaBuilder::new()
.control_with_shutdown(|
service: impl ControlApi<GrpcCallbackUrl, GrpcCallbackUrl>,
graceful_shutdown: impl Future<Ouput = ()>
| {
tonic::transport::Server::builder()
.add_service(ControlApiServer::new(service))
// ^^^^^^^^^^^^^^^^ generated by `tonic`
.serve_with_shutdown(bind_addr, graceful_shutdown.map(drop))
.await
})
.callback_factory(GrpcCallbackFactory)
.run()
.await
Discussed:
OnJoin
and OnLeave
, as there is no point in that. CallbackClientFactory
from the public API and leave only CallbackClient
. Factory is currently used to emulate connection pool, which should be client side implementation responsibility. Define `ControlApi` and `CallbackApi` traits in `medea-control-api-proto` crate (#55)
- provide common Rust definitions for Control API types
Synopsis
Define
ControlApi
andCallbackClient
traits to be able to provide not onlygrpc
protocol.Checklist
Draft:
prefixk::
labels appliedDraft:
prefix is removed