# README
Проект выполнен в рамках курса Route256 2021 OZON и является форком репозиториев раз и два.
Репозиторий с заданиями
https://github.com/ozonmp/omp-docs
О проекте
Проект включает в себя помимо настоящего репозиториия, ещё два:
- https://github.com/hablof/omp-bot — телеграм бот
- https://github.com/hablof/logistic-package-api-facade — фасад
gRPC-server
Первый из двух бинарников, собирающихся из данного репозитория — gRPC-server.
API
Protobuf контракт API описан в api\hablof\logistic_package_api\v1\logistic_package_api.proto
, предоставляет CRUD-методы. Код grpc объектов, методов, валидации вынесен в отдельный модуль pkg\logistic-package-api
.
В обработчиках запросов имеется возможность поднять уровень логирования с помощью метаданных запроса. Для этого необходимо передать по ключу "log_level"
значение "debug"
.
Service
Слой сервиса не содержит логики домена и создан исключительно в целях разделения пакетов api
и repo
(отсутствуют импорты).
Repository
Данные хранятся в Postgres. Методы пакета repo
повторяют методы api
, однако, при этом, реализуют паттерн transactional outbox. Помимо изменения основной таблицы, хранящей записи о сущностях домена package
, при выполнении CUD-методов добавляется запись в таблицу package_event
, описывающая произошедшие изменения.
Текст SQL-запросов собирается с помощью squirell
Миграции
Миграции описаны в db\migrations
.
Индексы созданы:
- на столбце
package_id
в таблицеpackage
, поскольку по нему идёт условиеWHERE
в запросеDescribe
- на столбце
package_event_id
в таблицеpackage_event
, поскольку по нему идёт условиеWHERE
в запросах Cleaner'а (см. ниже) - на столбце
event_status
в таблицеpackage_event
, поскольку по нему идёт условиеWHERE
в запросах Consumer'а (см. ниже)
Retranslator
Второй бинарник — retranslator. Работает в асинхронном режиме. Состоит из:
consumer
producer
sender
cleaner
Термины consumer
и producer
употреблены по отношению к внешнему миру.
Consumer
По таймеру горутины consumer
'ов "забирают" из таблицы package_event
данные о событии репозитория на обработку: читают записи и изменяют значение в столбце event_status
на Locked
. Полученные данные отправляются в буферизированный канал eventsChannel
.
Producer
Горутины producer
'ов читают данные из eventsChannel
и пытаются отправить их в кафка-топик вызывая методы sender
'а. Пишут в буферизированный канал cleanerChannel
сообщение с id
события и результатом отправки в кафку.
Cleaner
Если отправка в кафку была успешна, cleaner
удаляет из репозитория запись о событии, если неуспешна — cleaner
возвращает значение в столбце event_status
на значение по умолчанию Unlocked
. Запись события готова к повторной обработке.
Cleaner пытается набрать батч событий и обработать их в базе одним запросом. Если батч не накапливается, обработка вызывается принудительно по таймеру.
Sender
Sender сериализует данные о событиях в protobuf и отправляет в топик omp-package-events
.
Предусмотрены повторные попытки отправки с некоторым интервалом.
Код модели вынесен в отдельный модуль pkg\kafka-proto
.
At-least-once
Порядок действий при завершении работы ретранслятора позволяет избежать потерь сообщений.
Метрики
Сервисы собирают метрики с помощью прометей-клиента.
gRPC-server
grpc-сервер собирает две метрики:
logistic_package_api_not_found_total
Counter — общее количество NotFound событийlogistic_package_api_cud_event_total
Counter — общее количество CUD событий
Метрики grpc-сервера доступны на :9100/metrics
Retranslator
Ретранслятор собирает одну метрику
logistic_package_api_retranslator_events_processing
Gauge — количество событий, обрабатываемых в текущий момент в ретрансляторе
Метрики ретранслятора доступны на :9101/metrics
Grafana и Prometheus
С заданным интервалом Prometheus считывает метрики сервисов. Метрики запрашиваются Grafan'ой и отображаются на графике: logistic_package_api_retranslator_events_processing
— напрямую, а logistic_package_api_not_found_total
и logistic_package_api_cud_event_total
— рассчитывая количество происходящих событий в секунду в окне в 1 минуту.
Grafana доступна на :3000
Jaeger
Обработчики запросов grpc-серверa записывает трейсы и отправляет их в Jaeger. Трейсы имеют вложенные спаны методов репозиторя и SQL-запросов.
Jaeger доступен на :16686
Docker
Описаны докерфайлы для образов grpc-серверa и ретранслятора.
В docker-compose прокидываются конфиги для gRPC-сервера, ретранслятора, бота и фасада.
Makefile
В мейкфайле описаны команды для локального запуска приложения, для генерации protobuf модулей с помощью утилиты buf, сборки докер-образов, и их запуска.