docker-compose up --buildЗапуск тестов:
go test -vcurl -X POST http://localhost:8080/api/auth -H "Content-Type: application/json" -d "{\"username\":\"testuser\",\"password\":\"testpass\"}"curl -X GET http://localhost:8080/api/buy/pink-hoody -H "Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwiZXhwIjoxNzM5NTQ5NTc1fQ.Qb8qvOCCAyjWEqwiiWC4C4E0UyTAEq76bOekmYnYea4"curl -X GET http://localhost:8080/api/info -H "Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwiZXhwIjoxNzM5NTQ5NTc1fQ.Qb8qvOCCAyjWEqwiiWC4C4E0UyTAEq76bOekmYnYea4"curl -X POST http://localhost:8080/api/sendCoin -H "Content-Type: application/json" -H "Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwiZXhwIjoxNzM5NDYzOTIyfQ.w2LSqp6EdV8Z0NZWdb0T_RDDrNU2_kcEhaWzhabggzg" -d "{\"toUser\":\"anotheruser\",\"amount\":50}"API дан и структурирован – swagger.io позволяет сгенерировать сервер на основе данной конфигурации, поэтому использовал его. Оставалось реализовать логику ручек, связь с БД, авторизацию.
Выделены сущности:
-
Пользователь (
users)id SERIAL PRIMARY KEY– уникальный идентификатор пользователяusername VARCHAR(255) UNIQUE NOT NULL– имя пользователя (уникальное)password VARCHAR(255) NOT NULL– хешированный парольcoins INT DEFAULT 1000– количество монет у пользователя
-
Покупки (
purchases)id SERIAL PRIMARY KEY– уникальный идентификатор покупкиuser_id INT REFERENCES users(id)– связь с пользователемitem_name VARCHAR(255) NOT NULL– название купленного предметаcreated_at TIMESTAMP DEFAULT NOW()– дата и время покупки
-
Транзакции (
transactions)id SERIAL PRIMARY KEY– уникальный идентификатор транзакцииsender_id INT REFERENCES users(id)– отправительreceiver_id INT REFERENCES users(id)– получательamount INT NOT NULL– сумма переводаcreated_at TIMESTAMP DEFAULT NOW()– дата и время транзакции
Связи:
purchases.user_id→users.id(один пользователь может иметь много покупок)transactions.sender_idиtransactions.receiver_id→users.id(пользователи могут отправлять друг другу монеты)
JWT хранится на стороне клиента, передается через заголовок Authorization. К каждому запросу на покупку, перевод или отображение данных прикрепляется JWT, который сервер парсит и использует для выполнения запросов к БД от лица пользователя.
Ранее не сталкивался с нагрузычными. Разобрался, написал скрипт k6, проверяющий сценарий авторизации пользователя и выполнение трёх типов запросов. Чтобы не возникало ошибок, когда у пользователей не хватает денег на перевод или покупку, сделал цену товаров 0 и установил возможность перевода 0 монет для теста.
-
При
RPS = 100всё работало стабильно, разве что send coin работал медленно.
-
При
RPS = 1000большинство запросов не выполнялось, поэтому добавил:- Кэширование токенов
- Индексирование в БД
- Использование горутин для обработки запросов к БД
После оптимизации стало лучше, но при высокой нагрузке остаются ошибки. Данный момент требует дополнительной проработки. Возможно проблема в скрипте, подходе тестирования.

Фокусировался на производительности для нагрузочных тестах, поэтому не хватило времени на полноценный рефакторинг кода. По неопытности допустил ошибку в unit-тестах и понял это под конец дедлайна – unit-тесты фактически взаимодействуют с реальной бд в Docker, что не соответствует принципу изоляции юнит-тестов. В идеале следовало использовать мок-базу данных (sqlmock или testcontainers).