rk_zenoh 0.2.0
rk_zenoh: ^0.2.0 copied to clipboard
Dart bindings for Zenoh over a narrow C ABI - publish, subscribe and liveliness for offline-first fleets, with an explicit answer to the stale Zenoh ID after a restart.
rk_zenoh #
Привязки Zenoh для Dart: публикация, подписка и признаки живости для парка устройств, который часть времени проводит без связи.
Под привязкой лежит небольшой крейт на Rust (rust/) поверх устойчивого
подмножества Zenoh 1.9. Он узкий намеренно: около тридцати функций вместо
восьмисот, одно правило владения вместо ста двадцати шести определений типов,
и каждое перечисление пересекает границу по имени.
final session = await ZenohSession.open(ZenohConfig(
mode: SessionMode.peer,
connect: ['tcp/127.0.0.1:7447'],
));
final alive = await session.declareLiveliness('telepos/alive/till-17');
final orders = await session.subscribe('telepos/till/till-17/cmd');
orders.samples.listen((s) => print('${s.key}: ${s.text}'));
await session.put('telepos/shop/3/heartbeat', utf8.encode('ok'));
await alive.close();
await session.close();
Ни один вызов не выполняется на изоляте вызывающего: пакет держит собственный рабочий изолят, и вся нативная часть живёт там.
Чего здесь нет, и почему это важно знать заранее #
Advanced Pub/Sub отсутствует. Кеш, история для опоздавших подписчиков,
обнаружение пропусков и восстановление — всё это в Zenoh закрыто признаком
unstable, а пакет его не включает. Это ровно та часть, из которой обычно
делают «работу без связи», поэтому её приходится строить над пакетом:
долговечное состояние живёт в базе, которая реплицируется, а эта ткань несёт
то, что происходит сейчас. Подписчик, который не слушал, ничего не пропустил —
для него сообщения не было.
По той же причине нет управления надёжностью на сообщение
(zenoh::qos::Reliability нестабилен) и истории признаков живости.
Zenoh не проходит NAT. Он ищет соседей многоадресной рассылкой в пределах одной сети и разносит сведения слухами, когда точка входа уже известна, но адреса, которые ему дают, обязаны быть маршрутизируемыми. Дотянуться до кассы за чужим роутером — работа relay, а не ткани.
Идентификатор Zenoh — это не адрес #
Пересозданная сессия получает новый Zenoh ID. Сообщения, отправленные на старый, принимаются успешно и не доставляются никуда — без ошибки. Для кассы, которая перезапускается при обновлении, это обычное событие, а не крайний случай.
Пакет заставляет выбрать явно, через ZenohIdentity:
ephemeral |
pinnedTo / derivedFrom |
|
|---|---|---|
| ID после перезапуска | новый | тот же |
| Кого адресуют | долговечное имя в ключе | сам ID |
| Требует TLS | нет | да, и пакет откажет без него |
Отказ не формальность: кто первым занял закреплённый ID, тот его и удерживает — измерено. Без сертификата любая машина в сети выключает кассу из ткани, просто загрузившись раньше.
Числа и то, как они получены, — в doc/stale-zid.md.
Границы устойчивого подмножества — в
doc/stable-subset.md.
Сборка нативной части #
cd rust && cargo build --release
Пакет — FFI-плагин Flutter: flutter build сам вызывает cargo и кладёт
библиотеку в приложение на Windows, Linux и Android. Каталога hook/ здесь
нет и не будет — само его присутствие ломает dart run, dart test и
flutter build. Механизм, три разных пути к cargo и порядок проверки на Mac —
в doc/native-build.md.
Вне собранного приложения библиотека ищется по явному пути, по переменной
RK_ZENOH_LIBRARY или рядом с исполняемым файлом; крейт — обычный
cdylib/staticlib с C ABI.
Куда библиотека доезжает:
| Цель | Состояние | Чем доказано |
|---|---|---|
| Windows | доезжает | rk_zenoh.dll рядом с runner собранного приложения |
| Linux | доезжает | librk_zenoh.so в bundle/lib/ приложения |
| Android | доезжает | найдена внутри распакованного APK на armeabi-v7a, arm64-v8a, x86_64 |
| macOS, iOS | написано, ни разу не собрано | Mac на проекте нет; файлы существуют, чтобы пакет не оказался неверным в день, когда Mac появится, и ни одно утверждение про них не проверено |
Лицензия #
MIT, автор Rob Kim. См. LICENSE. Сам Zenoh — Apache-2.0 или EPL-2.0.