2026-10-08 19:35:14 +03:00
2026-10-07 22:42:46 +03:00
2026-10-07 22:42:46 +03:00
2026-10-08 19:35:14 +03:00
2026-10-07 22:42:46 +03:00
2026-10-07 22:42:46 +03:00
2026-09-16 18:47:15 +00:00
2026-10-07 22:42:46 +03:00
2026-09-16 18:47:15 +00:00
2026-09-16 18:47:15 +00:00
2026-10-07 15:12:38 +03:00
2026-10-07 22:42:46 +03:00
2026-10-07 22:42:46 +03:00
2026-09-16 18:47:15 +00:00

SIRMENT/core

SIRMENT — сервер системы обмена данными Artex. Узлами могут быть роботы, операторские приложения и сервисы. Сервер управляет соединениями и сессиями и передаёт данные по заданным маршрутам.

Реализовано

  • Transport/TCP принимает соединения и читает JSON-пакеты, разделённые LF. TCP.run() запускает настоящий asyncio-сервер; src/main.py собирает Router и SessionManager и запускает TCP на 0.0.0.0:9000.
  • Session хранит состояние подключения, версию протокола, метаданные и последние данные по командам. Handshake проходит последовательность connection → token_ask → token_answer → handshake_ask → handshake_answer. После успешного ответа сессия переходит в air.
  • Heartbeat: клиент отправляет heartbeat_ask с payload, сервер отвечает heartbeat_answer и обновляет дедлайн.
  • Watcher: у каждой сессии есть собственная asyncio-задача, проверяющая дедлайн раз в секунду и передающая менеджеру событие disconnect.
  • Отключение закрывает транспорт и переводит сессию в stop. Менеджер сохраняет запись на время восстановления, затем удаляет её и маршруты.
  • Реконект создаёт новый UID и собственный handshake. В token_answer можно передать старые token и upf. Сессия в stop с совпадающим upf отдаёт динамические метаданные и последние данные; Router переносит исходящие маршруты и все входящие ссылки на новый UID. Старая сессия получает состояние migrated, поэтому перенос нельзя повторить.
  • Router передаёт полезную нагрузку отправителя каждому получателю. Session.send() запускает отправку фоновой задачей; маршрутизатор не ждёт завершения сетевой отправки.

Текущие сроки:

Условие Срок
От создания сессии до первого heartbeat, включая handshake 60 секунд
После каждого heartbeat 5 секунд
Сохранение отключённой сессии для восстановления 60 секунд

Проверка watcher выполняется раз в секунду: фактическое обнаружение таймаута может произойти позже дедлайна на период проверки. Сам event loop продолжает обслуживать остальные соединения во время asyncio.sleep().

in/out описывают типы портов будущего редактора узлов. active_in и active_out хранят динамическое состояние. Эти поля сами по себе не создают маршруты. Значение com и общее правило объединения метаданных при реконекте ещё не зафиксированы.

connection.payload.token — токен робота, сохраняемый в метаданных auth; его будущая проверка по whitelist роутера пока не реализована. UID/upf в token_answer служат отдельно для восстановления сессии.

По согласованному протоколу отказ handshake означает только буквальный JSON false; остальные значения status означают успех. Текущий if not status ещё использует ложность Python и расходится с этим правилом. Payload данных сохраняется и пересылается как JSON-значение без автокаста в словарь. Ошибка разбора входного пакета может завершить обработчик клиента; TCP-finally закрывает его сессию, остальные соединения продолжают обслуживаться.

Незавершённое и ограничения

  • GUI/API редактирования маршрутов; автоматическое создание маршрутов и правила подписок.
  • Авторизация. Совпадение UID/upf сейчас используется для восстановления и не заменяет полноценную авторизацию.
  • Полноценное переключение диалектов: используется v1; v2 и short содержат только черновые имена полей и не имеют полного набора команд.
  • WebSocket/Socket.IO (sio).
  • Сохранение сессий, данных и маршрутов после перезапуска процесса.
  • Отдельный ответ клиенту с результатом восстановления. Heartbeat подтверждает новый handshake, но не доказывает успешный перенос старой сессии.
  • Настройка адреса и порта через CLI/окружение: сейчас они заданы в main.py.

Актуальные результаты, ошибки реализации и ограничения проверки приведены в отчёте тестов. Изменения исходников сервера выполняет автор проекта; доработка тестов и документации не редактирует src.

Запуск

Версия Python указана в .py-version — Python 3.11. Из корня репозитория:

python -m pip install -r req.txt
python src/main.py

Общий клиент находится в отслеживаемом examples/client.py:

python examples/client.py rover --count 10 --interval 1
python examples/client.py rover --old-token 123 --old-upf 456

На Windows можно использовать src/start_server.bat и examples/start_client.bat; они берут Python из D:\_Programs\anaconda\envs\sites.

Тесты

python -m pip install -r req-dev.txt
python -m pytest -q --cov=src --cov-branch --cov-report=term-missing --cov-report=xml

Тесты используют общий клиент из examples/, поэтому не зависят от локальной игнорируемой папки src/.test. Интеграционные сценарии работают с настоящим TCP-сервером. Отдельно выполняется настоящий src/main.py в дочернем процессе. Подробности и команды запуска — в tests/README.md. Новые регрессии остаются обычными падающими тестами до исправления реализации.

Docker и CI

Тесты выполняются для Pull Requests в main и при ручном запуске workflow. Docker-образы собираются при push в deploy и создании тегов v*.*.*. Образ запускает python src/main.py.

Структура

src/          TCP, сессии, маршрутизатор и точка входа
examples/     Общий клиент и батник ручного запуска
tests/       Модульные, TCP-интеграционные и процессные тесты
Description
New, better iteration of ARTEX
Readme 115 KiB
Languages
Python 98.9%
Dockerfile 0.6%
Batchfile 0.5%