Dynamic control API exposed via gRPC
Closed this issue · 0 comments
Part of 0.2.0 Roadmap (#27)
Background
У medea предусмотренно динамическое Control API. На данный момент есть имплементация только статичекого Control API.
Problem to solve
Требуется разработать gRPC интерфейс для динамического обновления Control API спеки. На данном этапе нужно реализовать методы Create
, Delete
, Get
. Метод Apply
не является частью этой issue и будет реализован позже.
Possible solution
Выбор крейта для реализации gRPC сервера
На данный момент существует только два относительно популярных и живых крейта для реализации gRPC. Это grpc и grpcio, поэтому выбор можно ограничить ими двумя.
grpc
Плюсы:
- полностью написан на Расте
- не требует внешних зависимостей
Минусы:
- довольно скудная документация
- проблемы с производительностью
grpcio
Плюсы:
- достаточно полная документация
- хорошая производительность
- обертка над официальной библиотекой gRPC следовательно есть надежда на бОльшую проработанность
Минусы:
- это обертка над библиотекой написанной на C++, и там возможны segfault'ы и прочие радости C/C++
- есть внешние зависимости в виде go (в случае если мы используем secure feature)
Тут все довольно неоднозначно, но все же grpcio выглядит более симпатично из-за лучшей документации и производительности. Но вообще крейт можно будет, скорее всего, в любой момент сменить без сильной боли, поскольку для десериализации обоими крейтами используется rust-protobuf, а взаимодействие с самим сервером выглядит достаточно тривиально. Также в процессе реализации при надобности можно будет использовать абстракции в виде trait'ов, чтобы легко переехать на другой крейт в случае необходимости.
Интеграция с уже существующей реализацией Control API
Для начала требуется сделать абстракции над источником данных. На данный момент в статическом Control API используются структуры десериализуемые с помощью serde
в случае с gRPC десериализация с помощью них не возможна, поэтому принято решение сделать trait'ы для всех необходимых на данный момент элементов, написать реализацию для уже существующих serde DTO и для gRPC DTO. Тут уже всплывает проблема, которая заключается в том, что DTO для grpcio генерируются автоматически и не очень хотелось бы дописывать что-то в автоматически сгенерированные файлы. Как вариант, конечно, не использовать build.rs
, а генерировать DTO'шки с помощью protoc
, но проблему пересборки protobuf спек с последующей перезаписью это не решает.
UPD: Все же было выбрано решение с реализацией TryFrom
для уже существующих элементов Control API, так как это позоволяет удобно прокидывать и обрабатывать ошибки в спеках.
Абстракции над элементами Control API
Это устаревший блок, поскольку была выбрана реализация с помощью TryFrom
.
Room:
trait RoomSpec {
fn members(&self) -> HashMap<MemberId, Box<dyn MemberSpec>>;
fn id(&self) -> RoomId;
}
Member:
trait MemberSpec {
fn webrtc_play_endpoints(&self) -> HashMap<WebRtcPlayId, Box<dyn WebRtcPlayEndpoint>>;
fn webrtc_publish_endpoints(&self) -> HashMap<WebRtcPublishId, Box<dyn WebRtcPublishEndpoint>>;
fn credentials(&self) -> String;
fn id(&self) -> MemberId;
fn get_webrtc_play_by_id(&self, id: WebRtcPlayId) -> Option<Box<dyn WebRtcPlayEndpoint>>;
fn get_webrtc_publish_by_id(&self, id: WebRtcPublishId) -> Option<Box<dyn WebRtcPublishEndpoint>>;
}
WebRtcPlayEndpoint:
trait WebRtcPlayEndpoint {
fn src(&self) -> SrcUri;
}
WebRtcPublishEndpoint:
trait WebRtcPublishEndpoint {
fn p2p(&self) -> P2pMode;
}