Ir al contenido

La pasada

Una pasada es un recorrido por cada familia cuyo intervalo ya ha vencido, salvo que el servicio en marcha arranca una familia de seis horas o más en cada pasada, más solo donde una no mantendría todas las cadencias, y deja las demás que tocan para los tics siguientes: las familias lentas se turnan. Es un incremento, no una reconstrucción: pide lo poco que puede haber cambiado desde la vez anterior, escribe lo obtenido en todos los almacenes configurados y anota cuándo corrió cada familia.

Dos cosas de ese diagrama son todo el diseño. Cada colector produce puntos fechados, y los almacenes que no pueden sostener una fecha los reciben ya reducidos a valores actuales, por el mismo reductor, antes de ver los datos. Ese es el tema de la fecha del punto.

Las superficies se mueven a velocidades muy distintas. Las ejecuciones de workflows terminan cada pocos minutos en una cuenta activa. Las etiquetas y los hitos se editan unas pocas veces por semana. La lista de forks cambia unas pocas veces al año. Un único intervalo para todas o malgastaría el límite de peticiones en las lentas o perdería las rápidas, así que cada familia lleva la suya.

FamiliaPor omisiónRecoge
actions15mEjecuciones de workflows, jobs, pasos, la caché de Actions
activity15mEl log de actividad del repositorio, donde queda un force push
events15mEl feed de eventos de la cuenta, que guarda solo los últimos 300
notifs15mLa bandeja de notificaciones
ratelimit15mLo que le queda por gastar al colector, en cada presupuesto
deployments30mDespliegues y sus entornos, en lote sobre todos los repositorios
account1hPerfil, calendario de contribuciones, totales
achievements1hLos distintivos del perfil, y lo que falta para el siguiente nivel
analyses1hAnálisis de code scanning, que GitHub poda
artifacts1hArtefactos y su caducidad
billing1hUso por día, producto, SKU y repositorio
commits1hLíneas cambiadas y estado de la firma, por commit
discussions1hLa mitad de foro de un repositorio
issueevents1hLa línea de tiempo de lo que se movió: etiquetas, asignaciones, transiciones
issues1hPull requests, issues y revisiones, uno a uno
outbound1hEstrellas dadas, y trabajo en repositorios ajenos
repo1hEstrellas, forks, lenguajes, temas, releases, rulesets
security1hAlertas de Dependabot y de code scanning
stars1hEstrellas por día de cada repositorio, y el recorrido de la lista de estrellas una vez, luego las cien más nuevas
totals1hLas cifras de siempre, preguntadas a GitHub en vez de sumadas aquí
planning6hEtiquetas e hitos
settings6hWebhooks y sus entregas, entornos, claves de despliegue
traffic6hLa ventana entera de 14 días, reescrita
forks12hQuién hizo fork, y cuándo
profile12hPaquetes, gists, cuentas sociales
stats12hCommits por semana, el punch card, las definiciones de workflow
branches24hQué ramas siguen vivas y cuánto hace que no se toca cada punta
inventory24hQué puede hacer el token del propio workflow, los dos almacenes de secretos, el code scanning por omisión
keys24hLas claves SSH y GPG de la cuenta, y cuándo caduca cada una
policyfiles24hSECURITY.md, CODEOWNERS, dependabot.yml y FUNDING.yml
rulesets24hCada versión del historial de cada ruleset
depsapagadaEl SBOM de dependencias de cada repositorio, y lo que cambió
historyapagadaEl calendario de contribuciones de cada año, el actual incluido
joblogsapagadaLa cola del log de cada job fallido

Poner cualquiera a 0 la apaga por completo. Ver cadencias.

La lista de repositorios se rehace una vez por hora, en la primera pasada que la encuentra con una hora de antigüedad, con medio tic de margen: una pasada lee su reloj unos milisegundos antes o después de la hora, y sin ese margen un repositorio creado entre medias esperaba un tic más. Los repositorios se crean pocas veces y listarlos cuesta una página por cada cien, así que cualquier cosa más corta gasta cuota para no aprender nada. Los forks y los archivados quedan fuera por omisión, por la razón que se expone en objetivos.

Una familia que falla en un repositorio se registra y se salta; la pasada continúa. Esto importa más de lo que parece, porque aquí “fallo” suele ser una función apagada: de cincuenta repositorios, la mayoría tiene Dependabot desactivado, y cada uno responde 403. Tratarlo como error perdería los otros cuarenta y nueve.

Hay una excepción, y es deliberada. Una familia en la que fallaron todos los repositorios no se marca como hecha. Marcarla escondería la caída hasta la siguiente cadencia, que para las familias de doce horas es medio día.

level=WARN msg="family failed everywhere, not marking it as run" family=security

state_file guarda nueve cosas, y las dos por las que se juzga una pasada son cuándo corrió cada familia por última vez y cuándo se vio cada repositorio por primera vez.

Lo segundo es lo que hace que el recorrido completo de la lista de stargazers ocurra una vez y no en cada pasada, como hace history_read con el historial diario de estrellas. Se escribe a través de un fichero temporal y se renombra, así que una caída a mitad de escritura no puede dejar un estado truncado que provocaría una recolección completa.

Junto a él el recolector guarda lo que hace barata una pasada y no lo que la hace completa: la caché de ETags, las ejecuciones de workflow cuyos jobs ya se escribieron, los rechazos y los tamaños de página de las pull requests, en <nombre>-cache.bin. Un reinicio lo vuelve a leer y empieza donde se paró el proceso anterior, no de cero, y borrarlo cuesta una pasada a precio completo de cada familia y no pierde nada.

Antes de cada familia el colector mira los tres cubos de límite de los que realmente gasta. Si alguno está en su reserva o por debajo y la ventana aún no se ha reiniciado, la familia se salta y se registra un aviso en vez de gastar el presupuesto hasta la última llamada. Ver límites de la API.

Un relleno histórico es la intención contraria: espera a que la ventana se renueve en vez de saltarse la familia.