From 2b04ba06b26cdccb625dd35440d691f1c7f9755a Mon Sep 17 00:00:00 2001 From: ilyabratskih Date: Sun, 1 Nov 2026 18:50:40 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 74 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 2006680..3ceaa8c 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,39 @@ -# Магазин - -Минимальный интернет-магазин: каталог, карточка, корзина и заказ без оплаты. - -Сайт открывается на [http://localhost:8088](http://localhost:8088). Порт 8080 на этой машине уже занят, поэтому gateway выведен на 8088. Консоль хранилища: [http://localhost:9001](http://localhost:9001) (`minio` / `minioadmin`). Образ `pgsty/silo` — публичная сборка MinIO: исходный `minio/minio` с Docker Hub больше не скачивается без аккаунта. - -## Запуск - -Нужен Docker. - -```bash -docker compose up --build -``` - -API, веб и бот поднимаются в двух репликах. Снаружи опубликован только gateway на порту 8080: он заново резолвит имя `web` и распределяет запросы по копиям. - -Бот молчит, пока в окружении нет токена. Чтобы включить его: - -```bash -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 — только для локального демо. +# Магазин + +Минимальный интернет-магазин: каталог, карточка, корзина и заказ без оплаты. + +Сайт открывается на [http://localhost:8088](http://localhost:8088). Порт 8080 на этой машине уже занят, поэтому gateway выведен на 8088. Консоль хранилища: [http://localhost:9001](http://localhost:9001) (`minio` / `minioadmin`). Образ `pgsty/silo` — публичная сборка MinIO: исходный `minio/minio` с Docker Hub больше не скачивается без аккаунта. + +## Запуск + +Нужен Docker. + +```bash +docker compose up --build +``` + +API, веб и бот поднимаются в двух репликах. Снаружи опубликован только gateway на порту 8080: он заново резолвит имя `web` и распределяет запросы по копиям. + +Бот молчит, пока в окружении нет токена. Чтобы включить его: + +```bash +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 — только для локального демо. + +## Запущенный пример +на веб - invix-test.bratskih.tech +бот тг - @invix_test12345_task_bot