# 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`.