Skip to content

boboliiiiiii/goboli

Repository files navigation

Goboli — Auction Platform (Telegram Gift Auctions)

Высоконагруженная платформа для многораундовых аукционов цифровых товаров с реал‑тайм UI.

Этот README включает:

  • понимание механики Telegram Gift Auctions;
  • явные допущения там, где поведение неочевидно;
  • архитектурные решения и почему они безопасны;
  • описание ключевых алгоритмов (см. docs/ALGORITHMS.md);
  • инструкции по запуску.

1) Понимание механики Telegram Gift Auctions

Telegram использует многораундовый формат:

  • аукцион состоит из нескольких раундов;
  • в каждом раунде часть участников получает товар;
  • остальные продолжают участие в следующих раундах;
  • есть защита от «снайперских» ставок в последнюю секунду.

Принятые допущения (явно)

  • Раунды: у аукциона фиксированы roundsCount и itemsPerRound.
  • Победители: победители — топ N по сумме ставки в текущем раунде.
  • Перенос ставок: проигравшие переносят ставку в следующий раунд; если раунд последний — средства возвращаются.
  • Anti‑snipe: если ставка попадает в топ в последние antiSnipeWindowSeconds, раунд продлевается на antiSnipeExtensionSeconds.
  • Баланс: ставка блокирует средства (available -> held), окончательное списание происходит при закрытии раунда.

2) Реализация backend и защита решений

2.1 Конкурентность и финансовая корректность

  • Все денежные операции идут через TX‑воркеры (Redis Streams): единый вход для команд hold_bid, close_round, deposit, set_balance.
  • Идемпотентность: все мутирующие запросы требуют Idempotency-Key — защита от повторной доставки и сетевых ретраев.
  • Redis как быстрый слой состояния: лидерборд и балансы обновляются атомарно.
  • Леджер в БД: LedgerTransaction и LedgerEntry фиксируют каждую операцию и позволяют проверять целостность.

Почему так: при одновременных ставках нельзя допускать двойных списаний или потери баланса; выбранный путь гарантирует воспроизводимость и проверяемость финансовых операций.

2.2 Закрытие раунда

Порядок закрытия:

  1. блокировка раунда (distributed lock),
  2. формирование победителей по лидерборду,
  3. списание у победителей и возвраты/перенос у проигравших,
  4. фиксация GiftAllocation,
  5. обновление статусов в БД и Redis.

2.3 Anti‑snipe

Если ставка попадает в топ в последние секунды, раунд продлевается — это снижает эффект «последнего клика» и повышает честность участия.

2.4 Нагрузка и боты

Встроен режим нагрузки:

  • админ может запускать/останавливать стресс‑ботов,
  • метрики (latency, error rate, rps) отображаются в админ‑панели,
  • есть кнопка очистки ботов и их ставок.

Это позволяет проверить систему под конкурентной нагрузкой и в конце раунда.

2.5 Пограничные случаи (учтено)

  • повторные запросы одной операции (идемпотентность);
  • одновременные ставки в последние секунды (anti‑snipe);
  • закрытие раунда при конкурирующих запросах;
  • недостаточный баланс и частичное удержание средств;
  • повторное закрытие раунда (идемпотентные ответы).

3) Минимальный UI

UI предназначен для демонстрации логики:

  • создание аукциона (без картинок),
  • участие в аукционе (ставки),
  • ставки от ботов,
  • просмотр состояния и результатов,
  • просмотр баланса.

Дизайн не оценивается, важна корректность логики.

4) Архитектура

flowchart LR;
  web["Web (Qwik)"];
  app["App (Elysia)"];
  redis[(Redis)];
  mongo[(MongoDB)];
  sozu["Sōzu reverse-proxy"];

  web <--> app;
  app --> redis;
  app --> mongo;
  sozu --> web;
  sozu --> app;
Loading

Сервисы

Сервис Порт Описание
web 4173 Qwik UI (static)
app 3000 HTTP API + WebSocket + воркеры
sozu 8080 reverse‑proxy (единая точка входа)

Вход в UI: http://localhost:8080

Технологии

  • Runtime: Node.js 20+
  • Frontend: Qwik + TypeScript
  • Backend: Elysia (HTTP + WebSocket + воркеры)
  • Database: MongoDB + Prisma
  • Cache/Streams: Redis (вспомогательный слой)
  • Monorepo: Yarn Workspaces + TurboRepo

Почему Elysia

Выбрал Elysia по практическим причинам:

  • высокая производительность и низкий overhead на запросах;
  • удобная типизация end‑to‑end (контракты, валидация, ответы);
  • простой и предсказуемый plugin‑подход без тяжёлой инфраструктуры;
  • встроенная поддержка WebSocket и middleware;
  • одинаковая модель для Node.js и Bun, без форков кода.

Это снижает стоимость поддержки и упрощает тестирование логики аукциона.

5) Запуск

Локально

corepack enable

yarn install
cp .env.example .env

docker compose up -d

Production (Docker)

docker compose build
docker compose up -d

6) Конфигурация

App

Переменная Описание Пример
API_PORT Порт HTTP сервера 3000
DATABASE_URL MongoDB connection string mongodb://localhost:27017/goboli?replicaSet=rs0
REDIS_URL Redis connection string redis://localhost:6379
TX_COMMANDS_STREAM Redis stream для команд tx:commands
REPLY_PREFIX Префикс reply streams reply:
CORS_ORIGIN Разрешённые origin *

TX (в составе App)

Переменная Описание Пример
TX_PERSIST_STREAM Stream для персистенции tx:persist
TX_GROUP Consumer group tx-workers
CONSUMER_NAME Имя консьюмера tx-1
TX_PERSIST_GROUP Consumer group для persist tx-persist
TX_PERSIST_CONSUMER_NAME Имя консьюмера persist tx-persist-1
ANTI_SNIPE_WINDOW_SECONDS Окно anti‑snipe 15
ANTI_SNIPE_EXTENSION_SECONDS Продление при anti‑snipe 10
ROUND_SWEEP_INTERVAL_MS Интервал проверки раундов 1000
ROUND_SWEEP_BATCH_SIZE Размер batch 25

7) API

Полная спецификация: services/app/openapi.yaml
Markdown версия: docs/OPENAPI.md

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages