Todo-list - сервис на Go
В процессе работы использованы:
- REST API
- Postgres
- Docker
- Swagger
Применены следующие пакеты:
gin - http фреймворк (работает быстрее стандартного net/http, позволяет создавать динамические маршруты).
viper - библиотека для работы с файлам конфигурации (папка config)
sqlx - библиотека для работы с БД
godotenv - библиотека для использования переменных окружения
logrus - библиотека для логирования
sha1 - библиотека для хэширования
jwt-go - библиотека для работы с токенами
strconv - библиотека для преобразования строк
swaggo/swag - библиотека для описания документации API
Функционал проекта:
- регистрация и аутентификация с помощью jwt токена
- создание, редактирование, получение и удаление списков и задач
- Graceful Shutdown
Структура проекта:
В папке cmd находиться основной main.go файл.
В папке pkg - вся логика приложения.
На верхнем уровне хранятся сущности (слой структуры данных):
server.go - со структурой http сервера.
user.go - файл с описанием структур пользователя
todo.go - файл с описанием структур листов, задач и их списков, а так же структур для их обновления
В pkg находятся три папки для соответствующих модулей:
handler - отвечает за роутинг, описывает endpoints, подключает соответствующие обработчики для них, использует мидлвару для записи id пользователя в контекст запроса. Это транспортный слой, слой работы с http.
Со структурой endpoints можно ознакомиться, открыв в браузере страницу localhost:8000/swagger/index.html
при запущенном локально приложении.
-->
service - модуль для бизнес логики, методов для работы с токенами и паролями
-->
repository - модуль для работы с БД
Схема приложения приведена на рисунке ниже:
При разработке использован метод "Чистой архитектуры от Дяди Боба" (https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html). Это позволяет: сделать систему гибкой и масштабируемой, независимо тестировать каждый слой системы, не зависеть от реализации пользовательского интерфейса и используемых технических решений в бизнес логике.
Мы можем в любой момент заменить базу данных на другую, и это никак не отразиться на остальной логике приложения
Основная задачи при таком методе - достичь разделения ответственности. Для этого применяется правило зависимости: "зависимости могут быть направлены только внутрь, более глубокая структура ничего не должна знать о более внешней".
Коммуникации между слоями происходят с помощью интерфейсов в repository и service, а также структур, реализующих их.
Работа базой данных:
Для запуска базы данных используется готовый docker-образ Postgres.
Всего в базе 5 таблиц: пользователи, списки задач, задачи, а также 2 дополнительные для связи между основными: список пользователей, список задач.
При запуске приложения с помощью docker-compose происходит миграция (переход к новой структуре базы данных) с помощью файлов из папки schema и docker-образа migrate.
Развёртывание локально:
При запуске приложения локально (с помощью go run cmd/main.go) необходимо:
- установить docker, утилиту migrate
- скачать образ Postgres, если он еще не скачан:
docker pull postgres
- запустить контейнер с БД командой:
docker run --name=todo-db -e POSTGRES_PASSWORD='111111' -p 5432:5432 -d --rm postgres
мы указываем имя контейнера и пароль для доступа к БД, прокидываем порт, на котором будет доступна БД, флаг -d говорит о запуске контейнера в фоновом режиме, --rm - удалит контейнер после его остановки - осуществить миграцию:
migrate -path ./schema -database 'postgres://postgres:111111@localhost:5432/postgres?sslmode=disable' up
утилита migrate будет использовать файлы миграций из папки schema для обновления структуры базы данных - убедитесь, что в файле configs/config.yml в поле db установлено следующее значение для хоста:
host: "localhost",
это необходимо для связи контейнера приложения с контейнером базы данных при работе приложения локально. - запустить приложение:
go run cmd/main.go
- при запуске приложение установит связь с контейнером базы данных на порту 5432,
- приложение работает на порту 8000, для тестирования сервиса можно использовать готовые описания запросов для Postman, они находятся в файле
Postman_req_todo-list.json
в репозитории
Развёртывание локально с помощью docker-compose:
Для запуска приложения с непосредственным билдингом образа приложения с помощью команды docker-compose up
:
- убедитесь, что docker-compose.yml для приложения
app
указана команда для для билдинга:
build: ./
она будет создавать новый образ приложения при каждом запуске docker-compose up
строчки для использования образа: image: account-name/app-name
быть не должно. - убедитесь, что в файле
configs/config.yml
в поле db
установлено следующее значение для хоста:
host: "db",
это необходимо для связи контейнера приложения с контейнером базы данных при запуске их совместно. - убедитесь, что у вас нет запущенных контейнеров на портах 5432 и 8000,
- запустить приложение:
docker-compose up
- при запуске приложение запустит контейнер базы данных, произведет миграцию ее структуры, сбилдит образ приложения и запустит из него контейнер,
- приложение работает на порту 8000, для тестирования сервиса можно использовать готовые описания запросов для Postman, они находятся в файле
Postman_req_todo-list.json
в репозитории
Развёртывание удаленно с помощью docker-compose:
- необходимо либо использовать мой образ:
gitint.elewise.com:5050/elma365-projects/hard-code/todo-list-service
- либо залить на DockerHub или Gitint свою версию образа приложения и использовать его.
При создании образа убедитесь, что в файле
configs/config.yml
в поле db установлено следующее значение для хоста:
host: "db",
Это необходимо для связи контейнера приложения с контейнером базы данных при запуске их совместно. - в docker-compose.yml для приложения
app
необходимо указать репозиторий, в котором храниться образ, например:
image: gitint.elewise.com:5050/elma365-projects/hard-code/todo-list-service
строчки для непосредственного билдинга build: ./
быть не должно. - на удаленном компьютере должен быть установлен Docker, можно воспользоваться статьей (https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04-ru) для его установки
- для запуска приложения на удаленном компьютере должены быть файл
docker-compose.yaml
и папка schema
с описаниями миграций, находиться они должны в одной папке - запускаем приложение командой:
docker-compose up
- Приложение работает на порту 8000 удаленного компьютера, для тестирования сервиса можно использовать готовые описания запросов для Postman, они находятся в файле
Postman_req_todo-list.json
в репозитории
Настройка Swagger:
В приложении используется Swagger. Он позволяет описать endpoints приложения в виде графического интерфейса. При запуске приложения локально с документацией можно ознакомиться в браузере по адресу:
localhost:8000/swagger/index.html
Для установки Swagger в приложении:
-
устанавливаем библиотеку swaggo/swag
go get -u github.com/swaggo/swag/cmd/swag
для Go 1.16 и выше
go install github.com/swaggo/swag/cmd/swag@latest
-
далее описываем главную аннотацию в main.go
-
описываем endpoints в модуле handler, непосредственно перед каждым методом обработчика
-
для генерации документации используем команду с указанием пути к файлу main.go
(если он не в корневой папке):
swag init -g cmd/main.go
Документация генерируется в папку docs.
-
так как применен фреймворк gin, необходимо:
импоритровать следующие библиотеки в handler.go
"github.com/swaggo/gin-swagger" // gin-swagger middleware
"github.com/swaggo/files" // swagger embed files
\_ "to-do-list/docs" // путь к папку docs, to-do-list - имя основного модуля из go.mod
инициализируем endpoint в handler.go
router.GET("/swagger/\*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
-
теперь можно ознакомиться с документацией по адресу localhost:8000/swagger/index.html
при запуске приложения удаленно, вместо localhost
указываем адрес вашей ВМ.