Materialized views — candidatos (analytics / dashboard)
Esboço para evolução futura alinhada ao inventário em database-access-fullstack-worker.md. Não aplicado automaticamente — rever índices e REFRESH em staging.
Objetivo
Reduzir leituras agregadas repetidas em messages (dashboard, analytics, rate-limit) substituindo ou complementando message-analytics-aggregates.ts e contagens no PrismaAnalyticsRepository.
Exemplo: agregado diário por tenant
-- Rascunho: ajustar colunas ao schema Prisma real
CREATE MATERIALIZED VIEW IF NOT EXISTS mv_message_daily_by_tenant AS
SELECT
tenant_id,
(created_at AT TIME ZONE 'UTC')::date AS day_utc,
environment::text AS environment,
status::text AS status,
COUNT(*)::bigint AS cnt
FROM messages
GROUP BY 1, 2, 3, 4;
CREATE UNIQUE INDEX IF NOT EXISTS mv_message_daily_by_tenant_uid
ON mv_message_daily_by_tenant (tenant_id, day_utc, environment, status);
Refresh concorrente (sem bloquear leituras da MV) após criar índice único:
REFRESH MATERIALIZED VIEW CONCURRENTLY mv_message_daily_by_tenant;
Operação
- Job agendado (cron / worker) com período alinhado ao SLA do dashboard (ex.: 1–5 min) ou refresh incremental via tabela de factos alimentada por triggers assíncronos.
- Manter
cacheAsidecomo camada quente; a MV alimenta o loader em cache miss ou substitui queries raw mais pesadas.
Relação com reconcilers
Os reconcilers do worker atualizam linhas de messages incrementalmente; após refresh da MV, totais por dia refletem mudanças. Para latência mínima entre evento e agregado, preferir incremental rollups (tabela message_daily_stats atualizada no write path) em vez de só REFRESH full.