feat(activity): S5 — query object ReactionSummary (#544) - #563
Open
davicbtoliveira wants to merge 3 commits into
Open
davicbtoliveira wants to merge 3 commits into
davicbtoliveira wants to merge 3 commits into
Conversation
Resume as reações de um conjunto de posts em número fixo de consultas: uma agregação `group by (timeline_id, reaction)` e, se houver usuário, uma leitura das linhas dele nos mesmos posts. Sem N+1 conforme a página cresce; a 2ª consulta não roda quando `userId` é null. Cada item vem como DTO `TimelineReactionSummary` (counts só > 0 + `mine` como `TimelineReaction`), seguindo a preferência do projeto por DTOs no lugar de arrays associativos. O agregado do Discord (`activity_reactions`) não entra na soma. Teste feature com `DB::listen` confirma ≤ 2 consultas para 3 e para 30 posts, e 1 consulta sem usuário. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- A agregação `group by` agora usa `toBase()`: a linha é um agregado, não
um `UserReaction`, e hidratar o model produzia registros parciais (sem
id) fáceis de confundir com linhas reais. O tipo do enum volta via
`TimelineReaction::from()`, com narrowing explícito das colunas.
- Helpers globais do teste ganham prefixo (`seedReactionSummaryPosts`,
`reactionSummaryQueries`) para não colidir com outros arquivos Pest,
que compartilham o mesmo processo.
- A contagem de consultas usa o query log da conexão, com reset em
`finally`, no lugar de um `DB::listen` que nunca era removido; o helper
devolve `[$result, $count]` e elimina o `use (&$summary)`.
- A asserção de `mine` nulo sem usuário lê como o critério de aceite
(`pluck('mine')->filter()` vazio) sem disputar com o Rector.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
hefeus
requested changes
Sep 16, 2026
Refactor query to map user reactions to timeline reactions. Signed-off-by: Davi Castello Branco Tavares de Oliveira <davicbtoliveira@hotmail.com>
6 tasks
AdryanneKelly
approved these changes
Sep 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contexto
A timeline web precisa exibir o breakdown de reações de cada post (
👍 3 · ❤️ 5) e destacar a reação do usuário atual, sem que o número de consultas cresça com o tamanho da página. Hoje o único caminho éwithCount('reactions'), que lê o agregado do Discord e não sabe "quem reagiu".Este PR entrega o S5 do PRD #539: o query object
ReactionSummary, que resume as reações de um conjunto de posts em número fixo de consultas lendo sóactivity_user_reactions:select timeline_id, reaction, count(*) ... where timeline_id in (...) group by timeline_id, reaction;userIdénull.Cada post volta como um DTO
TimelineReactionSummarycomcounts(só reações com contagem > 0, indexadas pelo value do enum) emine(?TimelineReaction). Todatimeline_idpedida tem um item na coleção, mesmo sem reações. A substituição dowithCount('reactions')no feed e no thread fica para o S8 (#547).Alterações
app-modules/activity/src/Reaction/Queries/ReactionSummary.php:forTimelines(iterable $timelineIds, ?string $userId): Collection<string, TimelineReactionSummary>, indexada portimeline_id. Deduplica ids e retorna coleção vazia sem tocar o banco quando a lista é vazia. A agregação usatoBase()para não hidratarUserReactionparciais; o enum volta viaTimelineReaction::from()com narrowing explícito das colunas.app-modules/activity/src/Reaction/DTOs/TimelineReactionSummary.php: DTOfinal readonlycomtimelineId,counts,minee os helperstotal()ecountOf(TimelineReaction).app-modules/activity/tests/Feature/Reaction/ReactionSummaryTest.php: 7 testes cobrindo o shape do breakdown,minenulo sem usuário, exclusão de posts não pedidos, ids repetidos, lista vazia e o custo constante de consultas (1 query sem usuário, ≤ 2 com usuário, mesmo número para 3 e 30 posts). A contagem usa o query log da conexão com reset emfinally; os helpers globais são prefixados para não colidir com outros arquivos Pest.Issues Relacionadas
Closes #544
Related to #539