---
# System prepended metadata

title: GoRanRouting

---

# GoRanRouting

# Задачи


1. Контракты для upstream-api (1 день, Алексей)
2. Создание интерфейсов, Добавление новой mock'ed-логики для Upstream/UpstreamAck (2 день, Александр)
3. Реализация всех нужных Интерфейсов (3 день, Алексей)
4. Ручное тестирование (1 день, Алексей\Александр)
5. Нагрузочное тестирование (1 день)
6. Правки по результатам нагрузочного тестирования (опционально, 0-4 дня):
    - Достаточно ли запросов в Posgres или нужно оптимизировать кеш?
    - Какие ещё оптимизации нужно добавить
8. Event pushing + connection killer (2 дня)
9. Инструментация кода (метрики, логи) (1 день)
10. Финальное тестирование (нагрузка, ручное) (1 день)
11. Приступить к реализации downstream


## Декомпозиция задач на неделю 24.04 - 30.04

Сущности:
- Challenge Registry (интерфейс + реализация, реализация в памяти)
- Расширение RoutingTable (интерфейс + реализация) для получения/обновления Trust

1. Контракты для upstream-api
    1. Сделать protobuf-репозиторий с контрактами для ran-routing (пока только upstream)
    2. Использовать эти контракты в goranrouting, отправить в новом формате клиенту

2. Создание контекста для ответа UpstreamAck на Upstream
    1. Приём и обработка (десериализация) UpstreamAck
    2. Реализация бизнес-логики обработки Upstream Ack/Reject
        1. Реализация MicChallenge
        2. Перерасчёт trust, обновление данных в БД (routing table)

3. Добавление логики в Upstream
    1. Создание MicChallenge при обработке 
    2. Создание контекста upstream/challenge
    3. Challenge Expiration

4. Если нужно, выбрать threadsafe хранилище данных кэша таблицы маршрутизации и остальных данных(MicChallenge).



## Декомпозиция задач на неделю 01.05 - 07.05

1. Обсудить изменения в протоколе - Не будет обратной совместимости с предыдущим ran-routing
    - rssi/snr раньше находился на уровне Radio, но это неправильно, в текущей версии этого нет
    - PB2 вместо Json (в текущей реализации есть только PB2)
    - etc..

Нужно будет сделать правки в бридже (на будущее)


2. Провести нагрузочное тестирование (Алексей)

Сделать программу, которая будет тестировать полный цикл upstream: 

gw -[upstream]-> ran-routing -[upstream]-> client -[ack]-> ran-routing

Профиль нагрузки должен быть похож на реальный use-case - Количество uplink в секунду (в RX window) для 1 клиента примерно равно кол-ву устройств у этого клиента.

Метрика 1 - Сколько сообщений отправил Gateway
Метрика 2 - Сколько обработал аплинков клиент


3. Правки (Саша)
- Убрать Notify из RoutingTable, перенести в ClientsRegistry
- TransactionId (реальные значения)
- Запускать изменения в кеше и в бд параллельно (подумать/протестировать)
- Challenge Expiration - через горутину в handleUpstream
- Инвалидировать кэш routing table (1rpm sync db)


Сделать нагрузочный тест + правки в upstream (до четверга)
После этого начать обсуждать разработку downstream


## Декомпозиция задач на неделю 08.05 - 14.05

Пересмотреть логику обработки даунстрима. Текущее решение не совсем корректное:
- Не поддерживает Deadline для Class C - нам либо нужно корректно его поддержать, либо перестать его использовать?
- Поддержка нескольких TxInfo в одном даунлинке?


Реализовать необходимую логику - хранение и управление данными, необходимыми для отправки даунлинка.
- ClassARegistry(devEui: GwInfo(tmst, snr, gwMac)) 
- ClassBRegistry(devEui: GwInfo(gwMac, supportClassB))
- ClassCRegistry(...)


DonwstreamHandler - 3 отдельных обработчика Class A / B / C - отдельные функции-замыкания (работают с registry).

Реализовать абстракцию для работы с гейтвеями через Redis - отправлять|получать данные.

Реализация получения ACK от гейтвея - скорее всего через Future, рассмотреть варианты реализации на Go.

Мультикаст :'<

Добавить в agent upstream страну и фильтровать по клиент + страна + (devAddr or devEUI)


## Декомпозиция задач на неделю 15.05 - 21.05

Закончить реализацию Registry для разных классов: 
- Добавить логику по сохранению GwInfo в обработку апстрима (+ подтверждение и удаление в класс A)
- Добавить периодические задачи по инвалидации гейтвеев

Вместо разных WS-соединений для upstream/downstream решено использовать 1 подключение. Для реализации этого подхода нужно выполнить следующие задачи:
- Правка контрактов для добавления всех возможных upstream/downstream сообщений
- "Демультиплексор", который будет вызывать нужные обработчики upstream/downstream сообщений
- 

TransactionId:
- Сделать маппинг transaction_id (используется в ran-routing) на downlink_id (используется в новом протоколе для гейтвеев) - необходимо для получения Ack.
- Или использовать новый формат transaction_id = строка, не int

Заменить все "заглушки" по работе с gateway-api (указывать верную модуляцию, etc.)




---

## Функции Upstream

Только функции ran-routing.
В этом списке не приведены задачи, связанные с дизайном/архитектурой приложения.

- [x] Получение upstream из redis (gateways)
    - [x] Работа с Redis-стримами
    - [x] Новый формат сообщений от upstream

- [x] WS connections management (clients)
    - [x] Реализация WS-сервера
    - [x] Авторизация пользователей (JWT)
        - [ ] Proper JWT validation (сейчас нет валидации с секретом, нужна ли она, если сейчас токен валидируется api-gateway?)
    - [x] Управление WS-подключениями (получить, отправить, закрыть, etc)
    - [x] Connections Killer (отключать WS-клиентов для expired токенов)

- [x] Работа с routing-table
    - [x] Работа с postgresql
    - [x] Кеширование данных об устройствах для клиента
    - [x] Периодическая синхронизация данных

- [x] Парсинг LoRa-сообщений

- [x] Контракты для upstream ran-routing
    - [x] Имплементация контрактов в protobuf
    - [x] Использование этих контрактов в SDK

- [x] MicChallenge & Trust
    - [x] Создание челленджей, вычисление complexity на основе trust
    - [x] Сохранение челленджей shared(redis)/local(memory)
    - [x] Challenge expiration
    - [x] Изменение значения Trust в БД, в зависимости от решенных челленджей

- [x] Upstream Ack/Reject handling
    - [x] Получение Challenge
    - [x] Обновление Trust
    - [x] Обновление TargetDevAddr/ActiveDevAddr

- [x] Заполнение данных для планирования даунлинка
    - [x] Создание DownstreamWindow для class A
    - [x] Подтверждение DownstreamWindow для class A (в процессе обработки UpstreamAck)
    - [x] Заполнение "таблицы маршрутизации" для даунлинков class B
    - [x] Заполнение "таблицы маршрутизации" для даунлинков class C

- [x] Usage Event pushing
    - [x] Redis client
    - [x] Отправка usage event'ов 

- [x] Configuration & Metrics
    - [x] Config loading (.env)
    - [x] Sentry sdk (?)
    - [x] Prometheus metrics
    - [x] Structured logging
    - [ ] Opentelemetry tracing (?)

- [ ] Misc
    - [x] Нагрузочный тест upstream
    - [ ] ***[УДАЛЯЕТСЯ]*** Синхронизация счётчиков для hard limits - upstream_counter/downstream_counter
        - [ ] Добавить миграцию для удаления счётчиков из БД.
        - [ ] Обновить старый Ran-Routing полсе удаления счётчиков
        - [ ] Касательно миграций - обсудить, где должны жить миграции для ran-routing и как они должны работать?
    - [ ] ***[Пока не реализуем]*** Фильтрация uplink's по NetId
    - [ ] ***[Пока не реализуем, обрабатываем трафик в одном инстансе]*** Межсервисный correlation-id


## Функции Downstream

- [x] WS connections management (clients)
    - [x] Реализация WS-сервера
    - [x] Авторизация пользователей (JWT)
    - [x] Управление WS-подключениями (получить, отправить, закрыть, etc)

- [x] Registry by downlink class
    - [x] class A
        - [x] Получение DownstreamWindow
        - [x] "Закрытие" DownstreamWindow
        - [x] Инвалидация DownstreamWindow по времени
    - [x] Class B
        - [x] Получение лучшего гейтвея для отправки даунлинка
        - [x] Инвалидация списка гейтвеев по времени
    - [x] Class C
        - [x] Получение лучшего гейтвея для отправки даунлинка
        - [x] Инвалидация списка гейтвеев по времени

- [x] Handle downlink by class
    - [x] class A
    - [x] Class B
    - [x] Class C

- [x] Общие функции по отправка даунлинков
    - [x] Redis downstream (gateways) 
        - [x] Отправка даунлинков
        - [x] Получение Ack (с таймаутом)
    - [ ] ???

- [x] Контракты для downstream ran-routing
    - [x] Имплементация контрактов в protobuf
    - [x] Использование этих контрактов в SDK

- [x] Обработка Multicast downlinks
    - [x] Вся логика по отправки даунлинков, только для мультикастов

- [x] Usage Event pushing
    - [x] Redis client
    - [x] Отправка usage event'ов 

- [x] Configuration & Metrics
    - [x] Config loading (.env)
    - [x] Sentry sdk (?)
    - [x] Prometheus metrics
    - [x] Structured logging
    - [ ] Opentelemetry tracing (?)

- [x] Тесты downstream
    - [x] Нагрузочный
    - [x] Функциональный
    - [x] Unit-test



