API поиска фильмов на Go
Что может быть лучше практики - только еще больше практики. Работая архитектором, нельзя быть только теоретиком. Пробую на практических примерах реализовывать handler’ы для http, работу с БД PostgreSQL (а возможно и с другими попробую, например, Tarantool или YDB). Сервис поддерживает интерфейс REST. Для предотвращения RACE CONDITION добавлены Optimistic Lock с испольщованием проверки версии фильма. Протестировать состояние гонки можно с помощью, например следующей команды:
xargs -I % -P8 curl -X PATCH -d '{"runtime": "97 mins"}' "localhost:4000/v1/movies/4" < <(printf '%s\n' {1..8})
Также API имеет RateLimiter. В качестве реализции используется x/time/rate и метод на основе bucket’ов. Чтобы проверить ограничения на кол-во запросов можно выпонить, например, следующую команду:
for i in {1..6}; do curl http://localhost:4000/v1/healthcheck; done
Вместо localhost указать хост, на котором запущено приложение. Важный нюанс текущей реализации RateLimiter - список IP хранится в структуре в памяти. Т.е. в распределенном окружении каждый экземпляр приложения будет иметь свой список IP. Нужно выносить хранение и отслеживание списка IP-адресов и лимитов во внешнее распределенное хранилище, такое как Redis или Tarantool.
Структура проекта
Пакет internal/data:
- models.go - абстракция, для работы с БД
- movies.go - реализация абстрактной модели работы с БД для фильмов
- runtime.go - т.к. время фильма число, но в тектом “mins”, то есть обертка при преобразовании в JSON и обратно
Пакет internal/validator:
- validator.go - используется для валидации данных, которые поступают в запрсы к API
Пакет cmd/api:
- errors.go - кастомные ошибки для ответов на запросы к API
- healthcheck.go - handler для endpoint проверки работоспособности приложения
- main.go - основой файл с проверкой флагов запуска приложения, инициализацией БД и запуском http-сервера
- movies.go - handler’ы для /movies
- routes.go - route’ы для API
- helpers.go - вспомогательные функции, такие как прочитать иднтификатор из запроса, запистаь JSON и другие
migrations:
Чтобы выполнить накат миграции, нужно выполнить следующую команду:
migrate -path=./migrations -database=$URL_DB up
Или можно выполнить миграцию на конкретную версию:
migrate -path=./migrations -database=$URL_DB goto 1
Чтобы откатить изменеия можно выполнить:
migrate -path=./migrations -database=$URL_DB down
Или как и накат на определенную версию:
migrate -path=./migrations -database=$URL_DB down 1
Всместо -path можно еще использовать ключ -source для ресурсов миграции с удаленных репозиториев
Для создания новой миграции можно воспользоваться следующей командой:
migrate create -seq -ext=.sql -dir=./migrations migration_name