| api | ||
| bot | ||
| docker | ||
| web | ||
| README.md | ||
Магазин
Минимальный интернет-магазин: каталог, карточка, корзина и заказ без оплаты.
Сайт открывается на http://localhost:8088. Порт 8080 на этой машине уже занят, поэтому gateway выведен на 8088. Консоль хранилища: http://localhost:9001 (minio / minioadmin). Образ pgsty/silo — публичная сборка MinIO: исходный minio/minio с Docker Hub больше не скачивается без аккаунта.
Запуск
Нужен Docker.
docker compose up --build
API, веб и бот поднимаются в двух репликах. Снаружи опубликован только gateway на порту 8080: он заново резолвит имя web и распределяет запросы по копиям.
Бот молчит, пока в окружении нет токена. Чтобы включить его:
set BOT_TOKEN=123456:telegram-token
docker compose up --build
В Telegram: /catalog, /cart, /checkout. Имя и телефон бот хранит в Postgres, не в памяти процесса.
Что специально сделано stateless
- Сессия сайта — строка в
web_sessionsи HttpOnly-кука. Её принимает любая реплика API. - Корзина и заказ лежат в Postgres. Повторное добавление одного товара —
INSERT ... ON CONFLICT, две реплики не создают две строки. - Оформление блокирует строки корзины
FOR UPDATEи в той же транзакции пишет заказ. - Картинки читаются из MinIO. На диск контейнера они не сохраняются.
- Бот в режиме polling: одна реплика держит advisory lock и вызывает
getUpdates, вторая ждёт. Telegram не принимает два poller на один токен. Повторныйupdate_idотсекается первичным ключомtelegram_updates. Сообщения одного чата сериализуютсяpg_advisory_xact_lock. BOT_MODE=webhookиWEBHOOK_URLпереключают бота на webhook: lock не берётся, работают все реплики, дедупликация та же. Нужен публичный HTTPS, который Telegram достучится доbot:8081.
Пароли в compose — только для локального демо.