Files
GmRelayBot/docs/adr/0001-use-vertical-slice-native-aot-and-aspire.md

4.2 KiB
Raw Permalink Blame History

ADR-0001: Vertical Slice Architecture, Native AOT, BackgroundService и Aspire

Status

Accepted — 2026-04-03

Context

GM-Relay — Telegram-бот для автоматизации игровых сессий, развёрнутый на Raspberry Pi (ARM64) за NAT. Требования к стеку:

  • .NET 10 / C# 14 — целевой рантайм.
  • Native AOT — минимальный размер бинарника, мгновенный cold start на ARM64.
  • Raspberry Pi 5 — ограниченные ресурсы (4–8 ГБ RAM).
  • Long Polling — Pi за NAT, webhook невозможен без проброса портов.

Необходимо выбрать: архитектурный паттерн, планировщик задач, ORM и оркестрацию.

Decision

1. Vertical Slice Architecture (VSA)

Каждый use case реализован как вертикальный срез: Command/Query record + Handler. Handler содержит всю логику (SQL, Telegram API, валидацию) — без абстрактных репозиториев и сервисных слоёв.

Почему не Clean Architecture:

  • Бот с 5–7 use cases не нуждается в 4+ проектах и абстракциях.
  • Все зависимости (Npgsql, Telegram.Bot) стабильны — заменять их не планируется.
  • VSA позволяет добавлять фичи без рефакторинга существующих.

2. BackgroundService + PeriodicTimer (вместо Quartz.NET)

Два триггера расписания (T-24ч: подтверждение, T-5мин: ссылка) реализованы через BackgroundService с PeriodicTimer(TimeSpan.FromMinutes(1)).

Stateless-дизайн: сервис при каждом тике делает SELECT к PostgreSQL, обрабатывает найденные сессии и обновляет статус в БД. При перезагрузке — ничего не теряется.

Почему не Quartz.NET:

  • Quartz.NET не совместим с Native AOT (reflection-based job loading).
  • Для двух простых WHERE-запросов Quartz — overkill.
  • BackgroundService нативно поддерживается .NET и AOT.

3. Npgsql + Dapper.AOT (вместо EF Core)

EF Core 10 не совместим с Native AOT (reflection-heavy query pipeline, dynamic IL). Npgsql ADO.NET — полностью AOT-совместим. Dapper.AOT использует source generators для compile-time генерации маппинга.

Миграции — DbUp (embedded SQL scripts).

4. Aspire 13 для оркестрации

Aspire обеспечивает:

  • Автоматический запуск PostgreSQL в dev-среде.
  • Service discovery и передачу connection strings.
  • OpenTelemetry (traces, metrics, logs) из коробки.
  • Aspire Dashboard для мониторинга.

5. Telegram.Bot 22.x + Long Polling

  • Long Polling — единственный вариант для Pi за NAT.
  • Telegram.Bot поддерживает System.Text.Json source generators для AOT.

Consequences

Положительные

  • Один бинарник ~15–30 МБ для ARM64 (Native AOT, self-contained).
  • Мгновенный cold start (~50ms) на Raspberry Pi.
  • Простота: каждая фича — один файл, один handler.
  • Устойчивость к перезагрузкам: stateless scheduler + PostgreSQL.

Отрицательные

  • Ручной SQL: нет автогенерации запросов, миграции пишутся руками.
  • Нет LINQ-to-SQL: все запросы — строки, ошибки только в runtime.
  • DI без reflection: все handlers регистрируются явно (без assembly scanning).

Риски

  • Dapper.AOT — относительно молодой проект; при проблемах — fallback на чистый Npgsql.
  • Telegram.Bot AOT-совместимость может потребовать кастомного JsonSerializerContext.