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-интеграционные и процессные тесты