Skip to content

Latest commit

 

History

History
160 lines (121 loc) · 10.4 KB

12_README.md

File metadata and controls

160 lines (121 loc) · 10.4 KB

Домашнее задание №12 «Заготовка сервиса Календарь»

Необходимо реализовать скелет сервиса «Календарь», который будет дорабатываться в дальнейшем.

Описание того, к чему мы должны придти, представлено в техническом задании.


В репозитории представлена заготовка сервиса, позволяющая понять, что вообще происходит и получить вектор для дальнейшей доработки.

Этот код можно менять/удалять/добавлять каким-угодно способом по усмотрению разработчика.


На данный момент сервис будет состоять из следующих логически выделенных частей:

0) «Точка входа», запускающая сервис

Обычно располагается в cmd/. В main() происходит инициализация компонентов сервиса (клиент к хранилищу, логгер, конфигурация и пр.), конструирование главного объекта-сервиса на их основе и его запуск. Допускается использование https://github.com/spf13/cobra.

1) Конфигурирование сервиса

При необходимости создать отдельный пакет, отвечающий за работу с конфигом.

Сервис должен иметь конфиг, считываемый из файла. Для этого потребуется:

  • обработка аргументов командной строки;
  • чтение файла конфигурации формата json, yaml и пр. на выбор разработчика;
  • заполнение программной структуры конфига из файла (Unmarshal и пр. способы);
  • допустимо, если все действия выше за вас делает сторонний модуль.

Конфигурация понадобится для инициализации различных компонентов системы, её возможные поля будут рассмотрены далее.

Соответственно сервис будет запускаться командой вида

./calendar --config=/path/to/config.yaml

где --config - путь к файлу конфигурации.

В репозитории должен присутствовать образец конфига.

2) Логирование в сервисе

При необходимости создать отдельный пакет, отвечающий за работу с логером.

Параметры, которыми необходимо инициализировать логгер:

  • log_level - уровень логирования (error / warn / info / debug);
  • любые другие на усмотрение разработчика.

Логгер может быть как глобальной переменной, так и компонентом сервиса.

3) Работа с хранилищем

Создать отдельный пакет, отвечающий за работу с хранилищем.

Создать интерфейс хранилища событий, состоящий из методов для работы с ним:

  • добавление события в хранилище;
  • изменение события в хранилище;
  • удаление события из хранилища;
  • листинг событий;
  • пр. на усмотрение разработчика.

Описание сущности и методов представлено в ТЗ.

Создать объекты ошибок, соответствующие бизнес ошибкам, которые необходимо выделить. Например, ErrDateBusy - данное время уже занято другим событием.

Создать две реализации интерфейса выше:

  • in-memory: храним события в памяти (т.е. просто складываем объекты в словари/слайсы, не забывая про критические секции);
  • sql: храним события в полноценной СУБД путем использования SQL-запросов в соответствующих методах.

Вынести в конфиг параметр, отвечающий за то, какую из реализаций использовать при старте.

Для работоспособности второй реализации необходимо:

  • установить СУБД (например PostgreSQL) локально (или сразу через Docker, если знаете как);
  • создать базу данных и пользователя для проекта календарь;
  • реализовать схему данных (таблицы, индексы) в виде отдельного SQL или go-файла (файл миграции) и сохранить его в репозиторий;
  • применять миграции руками или на старте сервиса;
  • вынести настройки подключения к БД в конфиг проекта.

Полезные библиотеки:

Использовать ORM (например, gorm) не допускается.

Календарь должен использовать хранилище через интерфейс.

4) Запуск простого HTTP-сервера

Запуск календаря должен стартовать HTTP-сервер. host и port сервера вынести в конфиг.

На данном этапе сервер не должен быть связан с бизнес логикой приложения и должен иметь только один "hello-world" endpoint ("/", "/hello", etc.).

Информация об обработанном запросе должна выводиться в log-файл:

  • IP клиента;
  • дата и время запроса;
  • метод, path и версия HTTP;
  • код ответа;
  • latency (время обработки запроса, посчитанное, например, с помощью middleware);
  • user agent, если есть.

Пример лога:

66.249.65.3 [25/Feb/2020:19:11:24 +0600] GET /hello?q=1 HTTP/1.1 200 30 "Mozilla/5.0"

5) Юнит-тесты

Минимальный обязательный набор - тесты на in-memory реализацию хранилища (на основную логику, бизнес-ошибки и конкуррентно-безопасность).

Остальные тесты на усмотрение разработчика.

6) Makefile

Проект должен иметь в корне файлы go.mod и Makefile, последний должен описывать команды:

  • make build - скомпилировать бинарный файл сервиса;
  • [make run] - опционально, собрать и запустить сервис с конфигом по умолчанию;
  • make test - запустить юнит-тесты (с флагом -race);
  • make lint - запустить golangci-lint (при необходимости добавить свой .golangci.yml);
  • [make migrate] - опционально, если миграции применяются руками;
  • пр. на усмотрение разработчика

Об архитектуре

Проект должен следовать:

Важно понять, что в Go нет серебряной пули по архитектуре. Ссылки ниже могут дать полезные концепции, но не стоит слепо следовать им:

Используйте стандартный layout, соблюдайте направление зависимостей, выделяйте пакеты по концепции, не забывайте про внедрение зависимостей через интерфейсы и у вас всё получится!

Не забываем про стайл гайд, например:

В данном ДЗ не нужно

  • Реализовывать HTTP, GRPC и пр. API к микросервису.
  • Писать .proto-файлы.

Это всё будет позже.

Критерии оценки

  • Makefile заполнен и пайплайн зеленый - 1 балл
  • Понятность и чистота кода (включая факт, что проект разбит на пакеты по определенной логике) - до 2 баллов
  • Реализовано конфигурирование сервиса - 1 балл
  • Используется логгер и он настраивается из конфига - 1 балл
  • Реализовано хранилище:
    • in-memory - 1 балл
    • sql + миграции - 2 балла
  • Запускается простой HTTP-сервер, мидлвара удовлетворяет ТЗ - 1 балл
  • Присутствуют юнит-тесты - 1 балл

Зачёт от 7 баллов