## Техническое задание на сервис «Календарь» ### Общее описание Сервис "Календарь" представляет собой максимально упрощенный сервис для хранения календарных событий и отправки уведомлений. Сервис предполагает возможность: * добавить/обновить событие; * получить список событий на день/неделю/месяц; * получить уведомление за N дней до события. Сервис НЕ предполагает: * авторизации; * разграничения доступа; * web-интерфейса. ### Архитектура Полностью завершенный сервис состоит из 5 процессов. #### 1) API API предоставляет собой GRPC и HTTP интерфейсы для пользователей. API реализуют основные методы сервиса. Так как авторизация и разделение доступа выходят за рамки сервиса, мы предполагаем, что ID пользователя просто передается через параметры / метаданные / заголовок запроса. #### 2) Планировщик Планировщик - это фоновый процесс, который не взаимодействует с пользователем и выполняет периодические задания: * выбор событий, требующих уведомления и отправка уведомлений в очередь рассыльщику; * очистка старых (более 1 года назад) событий. #### 3) Рассыльщик Рассыльщик - это фоновый процесс, занимающийся отправкой уведомлений. В рамках задания нет необходимости реальной отправки сообщений, достаточно, если рассыльщик просто будет записывать их в лог / выводить в STDOUT. #### 4) СУБД Реляционная СУБД (например, PostgreSQL) - хранит информацию о событиях. #### 5) Очередь сообщений Очередь сообщений (RabbitMQ) - используется для передачи уведомлений от Планировщика Рассыльщику. ### Описание сущностей #### Событие Событие - основная сущность, содержит в себе поля: * ID - уникальный идентификатор события (можно воспользоваться UUID); * Заголовок - короткий текст; * Дата и время события; * Длительность события (или дата и время окончания); * Описание события - длинный текст, опционально; * ID пользователя, владельца события; * За сколько времени высылать уведомление, опционально. #### Уведомление Уведомление - временная сущность, в БД не хранится, складывается в очередь для рассыльщика, содержит поля: * ID события; * Заголовок события; * Дата события; * Пользователь, которому отправлять. ### Описание методов * Создать (событие); * Обновить (ID события, событие); * Удалить (ID события); * СписокСобытийНаДень (дата); * СписокСобытийНаНеделю (дата начала недели); * СписокСобытийНaМесяц (дата начала месяца). ### Конфигурация, логирование, контейнеризация Рекомендуется собирать проект в виде трех бинарных файлов, по одному на каждый микросервис. Каждый из сервисов должен принимать путь файлу конфигурации: ```text ./calendar --config=/path/to/calendar_config.yaml ./calendar_scheduler --config=/path/to/scheduler_config.yaml ./calendar_sender --config=/path/to/sender_config.yaml ``` Проект следует оформить в виде набора контейнеров для каждого из микросервисов. Поскольку запуск будет осуществлять в контейнерах - логи нужно печатать в STDOUT. Сервисы должны получать настройки (например, адрес и логин в СУБД) через переменные окружения. При желании можно использовать конфиг viper, с поддержкой переменных окружения. Развертывание микросервиса должно осуществляться командой `docker-compose up` в директории с проектом. ### Тестирование Для проекта необходимо реализовать интеграционные тесты, т.е. тесты проверяющие работу на уровне API. Интеграционные тесты можно создать с помощью BDD, а можно просто с помощью стандартного пакета `testing` и запускать их в отдельном контейнере в том же compose окружении, что и остальные микросервисы. В таком случае тесты смогут получать адрес работающего сервиса через переменные окружения, выполнять запросы к нему, а также проверять состояние базы данных и пр. ### Этапы разработки Разработка разделена на следующие этапы (ДЗ): * Разрабатываем скелет сервиса: конфигурирование, работа с базой, простой web-сервер. * Добавляем HTTP и GRPC API. * Выделяем Планировщик и Рассыльщик. Интегрируемся с очередью сообщений. * Создаем Docker-образы, docker-compose конфигурации, пишем интеграционные тесты. Таким образом, на каждом этапе мы получаем осмысленный проект.