Микросервис, хранящий информацию о sign-in и sign-out событиях [тестовое задание]
Самый простой и быстрый способ запустить сервис — использовать convenience скрипты run.sh
или run.ps1
(на Windows):
# Unix
bash run.sh
# Windows
.\run.ps1
Скрипт установит пароль для базы данных и вызовет docker compose up -d
, Swagger интерфейс будет доступен по адресу http://localhost:8080/swagger.
Для успешного запуска сервиса должны быть свободны порты 8080
и 5432
.
Всё то же самое можно сделать вручную:
- скопировать файл
.envexample
в файл.env
- задать пароль для базы данных в переменной окружения
PG_PASS
- вызвать
docker compose up -d
- ASP.NET Core, .NET 7
- Dapper
- PostgreSQL + jsonb
- Serilog
- Swagger для документации API
- FluentValidation для валидации
- FluentMigrator для создания и выполнения миграций
- Mapster маппер
- xUnit для Unit тестирования
- xUnit, TestContainers и FluentAssertions для интеграционного тестирования
При выборе хранилища я руководствовался двумя основными принципами:
- Хранилище должно соответствовать требованиям; добавление каких-либо данных в модель события не должно стать проблемой (а в идеале — без вмешательства разработчика)
- Я должен хорошо уметь работать с этим хранилищем, поскольку в том случае, если бы в этом сервисе был заинтересован бизнес, мне, во-первых, нужно было бы иметь необходимый уровень экспертизы изначально, а во-вторых различные эксперименты могут быть затратны и финансово
Я думаю, что одним из лучших вариантов для хранения такого рода событий был бы ElasticSearch, но, к сожалению, я работал с ним только как с лог-аггрегатором и экспертизы у меня недостаточно. Поэтому остановился на PostgreSQL и следующем формате данных:
- Событие делится на метаданные и payload
- В метаданные входит информация, которая с наибольшей вероятностью будет востребована всегда, например, uuid пользователя или время регистрации события
- Payload — набор данных, формат которого определяет клиент
- Для метаданных используется обычная статичная конфигурация, колонки примитивных типов в реляционной базе данных, для payload используется колонка типа
jsonb
Таким образом клиент может прислать вложенный объект json
, который будет сохранён в базе данных — в queryable-виде, т.е. posrtgres позволяет проводить фильтрацию по jsonb
колонке — и вернётся этот объект в таком же виде. Подобный фильтр пока не реализован, доступны только фильтры по метаданным, однако он, во-первых, технически реализуем, просто я не успел этого сделать, во-вторых для этого всё готово. Даже без такого фильтра frontend-клиент, с функционалом, аналогичным, например, Grafana, сможет распарсить payload и организовать по нему поиск без необходимости делать этого на бэкенде (как это делается с логами в grafana loki).
Swagger-интерфейс развёрнутого сервера можно посмотреть вот здесь: