mirror of
				https://github.com/3ybactuk/marketplace-go-service-project.git
				synced 2025-10-31 06:23:44 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			275 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			275 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # Домашнее задание по модулю "Основы Go"
 | ||
| 
 | ||
| Необходимо реализовать сервис для работы с корзиной пользователя Cart
 | ||
| 
 | ||
| ## Основное задание
 | ||
| 
 | ||
| Необходимо имплементировать сервис, отвечающий за работу с корзиной пользователя (сервис Cart). Логика работы методов
 | ||
| и их контракты описаны ниже.
 | ||
| 
 | ||
| Требования к решению:
 | ||
| 
 | ||
| 1. Используем HTTP, на основе стандартной библиотеки Go 1.23
 | ||
| 2. Для определения существования товара делаем поход в сервис `product-service`
 | ||
| 3. Состояние храним в in-memory, персистентное хранилище на данный момент не требуется
 | ||
| 4. Никакого резерва стоков не делаем, логика простейшая
 | ||
| 
 | ||
| ## Дополнительное задание
 | ||
| 
 | ||
| 1. Делаем Middleware, который будет логировать поступающие запросы
 | ||
| 2. Делаем валидацию входящих структур на основе любой Open Source библиотеки (можно подсмотреть
 | ||
|    тут - https://awesome-go.com/validation/)
 | ||
| 3. Делаем ретраи в `product-service` на 420/429 статус в виде Client Middleware. 3 ретрая, потом ошибка
 | ||
| 
 | ||
| ## Спецификация
 | ||
| 
 | ||
| ### Добавить товар в корзину
 | ||
| 
 | ||
| Идентификатором товара является числовой идентификатор SKU. Метод добавляет указанный товар в корзину 
 | ||
| определенного пользователя. Каждый пользователь имеет числовой идентификатор userID. При добавлении в корзину 
 | ||
| проверяем, что товар существует в специальном сервисе.
 | ||
| 
 | ||
| Один и тот же товар может быть добавлен в корзину несколько раз, при этом количество экземпляров складывается.
 | ||
| 
 | ||
| | Метод | URI                                             |
 | ||
| |-------|-------------------------------------------------|
 | ||
| | POST  | /user/<user_id>/cart/<sku_id>                   |
 | ||
| 
 | ||
| **Параметры запроса:**
 | ||
| 
 | ||
| | Параметр | Тип параметра | Тип данных | Пример | Описание                                                         |
 | ||
| |----------|---------------|------------|--------|------------------------------------------------------------------|
 | ||
| | user_id  | query path    | int64      | 1007   | Идентификатор пользователя, в корзину которого добавляется товар |
 | ||
| | sku_id   | query path    | int64      | 2008   | Идентификатор товара, добавляемого в корзину                     |
 | ||
| | count    | body          | uint32     | 12     | Количество товаров, добавляемое в корзину                        |
 | ||
| 
 | ||
| **Параметры ответа:**
 | ||
| 
 | ||
| отсутствуют
 | ||
| 
 | ||
| **Параметры ошибочных ответов:**
 | ||
| 
 | ||
| | Сценарий                                                                                  | HTTP код ошибки | Описание                                                                |
 | ||
| |-------------------------------------------------------------------------------------------|-----------------|-------------------------------------------------------------------------|
 | ||
| | Добавление валидного SKU для пользователя (user_id) с нулевым или отрицательным значением | 400             | Идентификатор пользователя должен быть натуральным числом (больше нуля) |
 | ||
| | Добавление SKU с нулевым или отрицательным значением                                      | 400             | SKU должен быть натуральным числом (больше нуля)                        |
 | ||
| | Добавление SKU с нулевым или отрицательным количеством (count)                            | 400             | Количество должно быть натуральным числом (больше нуля)                 |
 | ||
| | Добавление несуществующего SKU в корзину                                                  | 412             | SKU должен существовать в сервисе `product-service`                     |
 | ||
| 
 | ||
| **Диаграмма последовательности:**
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| ### Удалить товар из корзины
 | ||
| 
 | ||
| Метод полностью удаляет все количество товара из корзины пользователя. Если у пользователя вовсе нет данной позиции,
 | ||
| то возвращается такой же ответ, как будто бы все позиции данного sku были успешно удалены.
 | ||
| 
 | ||
| | Метод  | URI                                             |
 | ||
| |--------|-------------------------------------------------|
 | ||
| | DELETE | /user/<user_id>/cart/<sku_id>                   |
 | ||
| 
 | ||
| **Параметры запроса:**
 | ||
| 
 | ||
| | Параметр | Тип параметра | Тип данных | Пример | Описание                                                         |
 | ||
| |----------|---------------|------------|--------|------------------------------------------------------------------|
 | ||
| | user_id  | query path    | int64      | 1007   | Идентификатор пользователя, в корзину которого добавляется товар |
 | ||
| | sku_id   | query path    | int64      | 2008   | Идентификатор товара, удаляемого из корзины                      |
 | ||
| 
 | ||
| **Параметры ответа:**
 | ||
| 
 | ||
| отсутствуют
 | ||
| 
 | ||
| **Параметры ошибочных ответов:**
 | ||
| 
 | ||
| | Сценарий                                                         | HTTP код ошибки | Описание                                                                |
 | ||
| |------------------------------------------------------------------|-----------------|-------------------------------------------------------------------------|
 | ||
| | Удаление SKU с нулевым или отрицательным значением               | 400             | SKU должен быть натуральным числом (больше нуля)                        |
 | ||
| | Удаление SKU с нулевым или отрицательным пользователем (user_id) | 400             | Идентификатор пользователя должен быть натуральным числом (больше нуля) |
 | ||
| 
 | ||
| **Диаграмма последовательности:**
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| ### Очистить корзину пользователя
 | ||
| 
 | ||
| Метод полностью очищает корзину пользователя. Если у пользователя нет корзины или она пуста, то, как и при успешной
 | ||
| очистке корзины, необходимо вернуть код ответа 204 No Content.
 | ||
| 
 | ||
| | Метод  | URI                  |
 | ||
| |--------|----------------------|
 | ||
| | DELETE | /user/<user_id>/cart |
 | ||
| 
 | ||
| **Параметры запроса:**
 | ||
| 
 | ||
| | Параметр | Тип параметра | Тип данных | Пример | Описание                                                         |
 | ||
| |----------|---------------|------------|--------|------------------------------------------------------------------|
 | ||
| | user_id  | query path    | int64      | 1007   | Идентификатор пользователя, в корзину которого добавляется товар |
 | ||
| 
 | ||
| **Параметры ответа:**
 | ||
| 
 | ||
| отсутствуют
 | ||
| 
 | ||
| **Параметры ошибочных ответов:**
 | ||
| 
 | ||
| | Сценарий                                                             | HTTP код ошибки | Описание                                                                |
 | ||
| |----------------------------------------------------------------------|-----------------|-------------------------------------------------------------------------|
 | ||
| | Удаление корзины с нулевым или отрицательным пользователем (user_id) | 400             | Идентификатор пользователя должен быть натуральным числом (больше нуля) |
 | ||
| 
 | ||
| **Диаграмма последовательности:**
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| ### Получить содержимое корзины
 | ||
| 
 | ||
| Метод возвращает содержимое корзины пользователя на текущий момент. Если корзины у переданного пользователя нет,
 | ||
| либо она пуста, следует вернуть 404 код ответа. Товары в корзине упорядочены в порядке возрастания sku.
 | ||
| 
 | ||
| | Метод | URI                      |
 | ||
| |-------|--------------------------|
 | ||
| | GET   | /user/<user_id>/cart     |
 | ||
| 
 | ||
| **Параметры запроса:**
 | ||
| 
 | ||
| | Параметр | Тип параметра | Тип данных | Пример | Описание                                                         |
 | ||
| |----------|---------------|------------|--------|------------------------------------------------------------------|
 | ||
| | user_id  | query path    | int64      | 1007   | Идентификатор пользователя, в корзину которого добавляется товар |
 | ||
| 
 | ||
| **Параметры ответа:**
 | ||
| 
 | ||
| | Параметр       | Тип данных | Пример                                           | Описание                                     |
 | ||
| |----------------|------------|--------------------------------------------------|----------------------------------------------|
 | ||
| | items[i].sku   | int64      | 2008                                             | Идентификатор товара в корзине пользователя  |
 | ||
| | items[i].name  | string     | "Гречка пропаренная, в пакетиках для варки, 400" | Наименование товара                          |
 | ||
| | items[i].count | uint32     | 10                                               | Количество единиц товара                     |
 | ||
| | items[i].price | uint32     | 16                                               | Стоимость единицы товара в условных единицах |
 | ||
| | total_price    | uint32     | 160                                              | Суммарная стоимость всех товаров в корзине   |
 | ||
| 
 | ||
| 
 | ||
| **Пример ответа:**
 | ||
| 
 | ||
| ```json
 | ||
| {
 | ||
|     "items" : [
 | ||
|         {
 | ||
|             "sku": 2958025,
 | ||
|             "name": "Roxy Music. Stranded. Remastered Edition",
 | ||
|             "count": 2,
 | ||
|             "price": 1028
 | ||
|         },
 | ||
|         {
 | ||
|             "sku": 773297411,
 | ||
|             "name": "Кроссовки Nike JORDAN",
 | ||
|             "count": 1,
 | ||
|             "price": 2202
 | ||
|         }
 | ||
|     ],
 | ||
|     "total_price": 4258
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| **Параметры ошибочных ответов:**
 | ||
| 
 | ||
| | Сценарий                                                           | HTTP код ошибки | Описание                                                                |
 | ||
| |--------------------------------------------------------------------|-----------------|-------------------------------------------------------------------------|
 | ||
| | Запрос корзины с нулевым или отрицательным пользователем (user_id) | 400             | Идентификатор пользователя должен быть натуральным числом (больше нуля) |
 | ||
| 
 | ||
| 
 | ||
| **Диаграмма последовательности:**
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| ## Взаимодействие с Product service
 | ||
| 
 | ||
| Если, вызвав `make run-all`, развернуть деплоймент, swagger этого сервиса  
 | ||
| можно увидеть локально по адресу: [http://localhost:8082/docs/](http://localhost:8082/docs/)
 | ||
| 
 | ||
| Сервис поддерживает следующие операции:
 | ||
| 
 | ||
| 
 | ||
| #### GET /product?count=10&start_after_sku=0
 | ||
| 
 | ||
| Эта операция имеет два необязательных параметра:
 | ||
| - `count` — сколько элементов вернуть и
 | ||
| - `start_after_sku` — после какого элемента начать вывод.
 | ||
| 
 | ||
| Response:
 | ||
| ```
 | ||
| [
 | ||
|     {
 | ||
|         name  string
 | ||
|         price int32
 | ||
|         sku   int64 
 | ||
|     },
 | ||
| ]
 | ||
| ```
 | ||
| 
 | ||
| #### GET /product/<sku>
 | ||
| 
 | ||
| Эта операция выводит данные товара с заданным `sku`.
 | ||
| 
 | ||
| Response:
 | ||
| ```
 | ||
|     {
 | ||
|         name  string
 | ||
|         price int32
 | ||
|         sku   int64 
 | ||
|     }
 | ||
| ```
 | ||
| 
 | ||
| Обратите внимание, сервис `product-service` отдаёт цены в `int32` формате.  
 | ||
| В JSON нет беззнаковых целых, поэтому `int32`.  
 | ||
| Вам же, внутри своих сервисов, для совместимости их между собой  
 | ||
| следует использовать беззнаковый тип `uint32`.
 | ||
| 
 | ||
| Также следует обратить внимание на то, что он выведен на `localhost:8082` лишь  
 | ||
| для вашего удобства работы с данными.
 | ||
| 
 | ||
| Ваш сервис `cart`, запущенный докер-контейнером, сможет подключиться к `product-service`  
 | ||
| по адресу `product-service:8082` — заниматься маршрутизацией будет сам докер.
 | ||
| 
 | ||
| Авторизация на запрос выполняется с помощью заголовка `X-API-KEY` и токена `testToken`.
 | ||
| 
 | ||
| ## Makefile
 | ||
| 
 | ||
| В рамках данного задания необходимо имплементировать следующие таргеты:
 | ||
| 
 | ||
| - run-all — запускает сервисы. На данный момент их должно стать два:
 | ||
|   - `product-service` — уже реализован
 | ||
|   - `cart` — разрабатываемый вами в качестве домашнего задания
 | ||
| 
 | ||
| ## Ожидаемый результат
 | ||
| 
 | ||
| - с помощью команды `make run-all` можно запустить приложение
 | ||
| - приложение слушает HTTP-запросы на порту 8080
 | ||
| - реализованы API-методы
 | ||
|   - POST   /user/<user_id>/cart/<sku_id>
 | ||
|   - DELETE /user/<user_id>/cart/<sku_id>
 | ||
|   - DELETE /user/<user_id>/cart
 | ||
|   - GET    /user/<user_id>/cart
 | ||
| - методы реализуют заявленную бизнес-логику
 | ||
| - методы валидируют запросы и отдают описанные в спецификации коды ошибок
 | ||
| - информация о пользователях и их состоянии корзины хранится в памяти приложения
 | ||
| - при рестарте приложения состояние системы теряется
 | ||
| 
 | ||
| ## Автоматические проверки
 | ||
| Ваше решение должно проходить автоматические проверки:
 | ||
| 
 | ||
| - Компиляция
 | ||
| - Линтер
 | ||
| - Unit-тесты (если есть)
 | ||
| - Автотесты
 | ||
| 
 | ||
| Прохождение автоматических проверок влияет на итоговую оценку за домашнюю работу.
 | ||
| 
 | ||
| ## Сценарии тестирования с примерами запроса (для тьютора)
 | ||
| 
 | ||
| Сценарий тестирования следует описать в [cart.http](./cart.http)
 | ||
| 
 | ||
| ### Дедлайны сдачи и проверки задания:
 | ||
| - 24 мая 23:59 (сдача) / 27 мая, 23:59 (проверка)
 | 
