Фабрика отчётов и сбор данных из разных источников
↑ 5.6 Генерация документов и отчётов · ← Предыдущая · → Следующая
Зачем это на собесе
Архитектурный вопрос: как спроектировать сервис отчётов, собирающий данные из нескольких систем.
Объяснение
Фабрика отчётов — компонент, который по типу отчёта выбирает провайдеры данных и рендерер, а затем формирует документ.
flowchart LR R[Запрос отчёта] --> F[ReportFactory] F --> P1[Провайдер: PostgreSQL] F --> P2[Провайдер: ClickHouse] F --> P3[Провайдер: внешний API] P1 & P2 & P3 --> M[Модель отчёта] M --> RN[Рендерер PDF/Excel/HTML] RN --> S[(MinIO)] S --> L[Ссылка клиенту]
Разделение ответственности:
| Часть | Задача |
|---|---|
| Определение отчёта | параметры, права доступа, формат |
| Провайдеры данных | получение данных из источников (параллельно, с таймаутами) |
| Агрегатор | объединение и расчёт итогов |
| Рендерер | вывод в формат; один набор данных → PDF/XLSX/CSV |
| Оркестрация | асинхронная задача, статус, повторы, отмена |
public interface IReportDefinition { string Type { get; } Task<ReportModel> BuildAsync(ReportRequest r, CancellationToken ct); }
public interface IReportRenderer { string Format { get; } Task RenderAsync(ReportModel m, Stream output, CancellationToken ct); }
public class ReportService(IEnumerable<IReportDefinition> defs, IEnumerable<IReportRenderer> renderers)
{
public async Task RunAsync(ReportRequest r, Stream output, CancellationToken ct)
{
var model = await defs.Single(d => d.Type == r.Type).BuildAsync(r, ct);
await renderers.Single(x => x.Format == r.Format).RenderAsync(model, output, ct);
}
}Долгие отчёты: POST /reports → 202 Accepted + Location: /reports/{id}; клиент опрашивает статус или получает уведомление (SignalR/вебхук).
Нюансы и подводные камни
- Отчёты на боевой БД нагружают её: читайте с реплики или из аналитического хранилища (ClickHouse).
- Согласованность данных из разных источников: фиксируйте момент среза.
- Права: пользователь видит только свои данные (фильтры на уровне провайдера).
- Ограничения: лимит на объём и время; отмена по токену.
- Кэшируйте готовые отчёты по параметрам.
Практика
- Реализуйте фабрику с двумя определениями и тремя рендерерами.
- Сделайте асинхронный API отчёта со статусом и ссылкой на файл.
- Ограничьте параллелизм сборки отчётов и добавьте отмену.
Вопросы с ответами
Как устроить сервис отчётов?
Отделить определения и провайдеры данных от рендереров, выполнять генерацию асинхронно и хранить результат в объектном хранилище.
Почему отчёты не стоит строить на основной БД?
Тяжёлые запросы мешают OLTP; используют реплику или OLAP-хранилище.