User story
Como o worker de coleta, eu quero ler o último refs_digest de cada repositório e janela por uma
rota autenticada, para descobrir o que está pendente sem receber credencial de banco.
Acceptance criteria
A query
select r.id as repository_id, w.window_days, l.refs_digest
from repositories r
cross join (values (7),(15),(30),(60),(90)) as w(window_days)
cross join lateral (
select refs_digest
from analysis_runs a
where a.repository_id = r.id
and a.window_days = w.window_days
and a.refs_digest is not null
order by a.created_at desc
limit 1
) l
where r.organization_id = $1;
Por que lateral e não distinct on
O Postgres não tem skip scan, então distinct on (repository_id) varre a tabela inteira: medido em
360 mil linhas — o que ~600 repositórios × 5 janelas acumulam em dois meses de ciclos —, dá 103 ms e
360 mil buffers. O lateral parte da lista de repositórios e faz uma busca no índice que para na
primeira linha: 32 ms e 8 mil buffers. O que decide não é o ganho de hoje, e sim como cada forma
cresce: o distinct on com o total de linhas da tabela, o lateral com o número de repositórios.
Por que refs_digest is not null no predicado
É o que separa o worker do agente local. O push local grava linha sem digest e, sendo a mais
recente, esconderia o watermark do worker — que reanalisaria o repositório em todo ciclo enquanto o
hook estivesse instalado.
Scope / non-goals
Dentro: a rota de leitura. Fora: o POST no mesmo caminho (issue irmã) e a seleção em si, que
mora no worker.
Se encaixa em qual estágio?
Stage 2 — Ingestion: token auth. É ela que evita dar credencial de banco ao CI.
Implementation notes
Ausência de linha significa pendente, que é o comportamento seguro: repositório nunca analisado
entra no primeiro ciclo. O índice de leitura que serve esta query vem na issue da migration 023.
Links
Bloqueado por
A coluna refs_digest e o índice de leitura: #217. Sem eles a rota existe mas erra em runtime — nada em uso quebra, porque ninguém a chama ainda.
User story
Como o worker de coleta, eu quero ler o último
refs_digestde cada repositório e janela por umarota autenticada, para descobrir o que está pendente sem receber credencial de banco.
Acceptance criteria
GET /api/ingest/watermarks— não existe hoje: sob/api/ingestsó há oPOSTe a/api/ingest/usage/api/ingest/usagejá usa (validateToken+supabaseAdmin)refs_digestorganization_iddo tokencross join lateral, nãodistinct onA query
Por que
laterale nãodistinct onO Postgres não tem skip scan, então
distinct on (repository_id)varre a tabela inteira: medido em360 mil linhas — o que ~600 repositórios × 5 janelas acumulam em dois meses de ciclos —, dá 103 ms e
360 mil buffers. O
lateralparte da lista de repositórios e faz uma busca no índice que para naprimeira linha: 32 ms e 8 mil buffers. O que decide não é o ganho de hoje, e sim como cada forma
cresce: o
distinct oncom o total de linhas da tabela, olateralcom o número de repositórios.Por que
refs_digest is not nullno predicadoÉ o que separa o worker do agente local. O push local grava linha sem digest e, sendo a mais
recente, esconderia o watermark do worker — que reanalisaria o repositório em todo ciclo enquanto o
hook estivesse instalado.
Scope / non-goals
Dentro: a rota de leitura. Fora: o
POSTno mesmo caminho (issue irmã) e a seleção em si, quemora no worker.
Se encaixa em qual estágio?
Stage 2 — Ingestion: token auth. É ela que evita dar credencial de banco ao CI.
Implementation notes
Ausência de linha significa pendente, que é o comportamento seguro: repositório nunca analisado
entra no primeiro ciclo. O índice de leitura que serve esta query vem na issue da migration 023.
Links
Bloqueado por
A coluna
refs_digeste o índice de leitura: #217. Sem eles a rota existe mas erra em runtime — nada em uso quebra, porque ninguém a chama ainda.