mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-12 22:13:05 +00:00
fix(archive): teto de 15 min no download do reparo e caminhos do runbook (C246-followup)
O canário 80/83 abortou no download do Flickr: original de ~54 MB (panorâmica 7952px) a ~260 KB/s no link direto do homeserver leva ~3,5 min, acima do teto de 2 min herdado do C231. ARCHIVE_INTEGRITY_DOWNLOAD_TIMEOUT_MS vira 15 min (exportada e pinada no unit); falha de download segue failed retentável. Runbook §C246 usa ~/archive-reports (o /srv do texto original não existe/grava) e ganha docker pull do migrator (a limpeza pós-deploy remove a tag local).
This commit is contained in:
parent
a3a49c3462
commit
255751f5ce
4 changed files with 27 additions and 8 deletions
1
docs/changelog/2026-10-02-c246-reparo-timeout.md
Normal file
1
docs/changelog/2026-10-02-c246-reparo-timeout.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
**C246-followup — teto do download do reparo e caminhos do runbook (2026-10-02):** o primeiro uso real do `pnpm archive:integrity --apply` em produção (canário 80/83) abortou os dois reparos no `download` do Flickr: o original é uma panorâmica de 7952px com **~54 MB** e a egress direta do homeserver estava a ~260 KB/s (~3,5 min), acima do teto de 2 min herdado da ingestão C231. O teto do download do reparo vira `ARCHIVE_INTEGRITY_DOWNLOAD_TIMEOUT_MS = 15 min` (constante exportada e pinada no unit), que ainda pega conexão travada sem cortar link lento-mas-funcional; falha de download continua `failed` retentável (nunca rebaixa). O runbook §C246 passa a usar `~/archive-reports` (o `/srv/archive-reports` do texto original não existe e não é gravável pela `fsolla`) e ganha o `docker pull` do migrator antes dos comandos — a limpeza pós-deploy remove a tag local e o registry preserva a imagem. Sem migration/UI; o restante da entrega (varredura + reparo + rebaixamento) fica intocado.
|
||||
|
|
@ -1438,7 +1438,7 @@ docker compose --profile maintenance run --rm \
|
|||
```
|
||||
|
||||
Os recibos JSON ficam em `data/archive/reports/` do container — monte um volume
|
||||
(`-v /srv/archive-reports:/app/data/archive`) para preservá-los. Guardas: fora de
|
||||
(`-v ~/archive-reports:/app/data/archive`) para preservá-los. Guardas: fora de
|
||||
teste o `TEQO_ENV=staging|production` é obrigatório com o **nome exato** do banco
|
||||
(`teqo_staging`/`teqo_1313`); `ALLOW_REMOTE_DB` é recusado; sem as 4 `S3_*` o
|
||||
`--apply` recusa (o acervo não estaria acessível no alvo); `ARCHIVE_CATALOG_CONFIRM=1`
|
||||
|
|
@ -1702,24 +1702,26 @@ canário primeiro:
|
|||
ssh homeserver
|
||||
cd ~/stack
|
||||
# 1) canário read-only nas fotos do achado (80/83) — não escreve:
|
||||
# (a limpeza pós-deploy remove a tag local do migrator; o registry a preserva)
|
||||
docker pull "$(docker inspect -f '{{.Config.Image}}' teqo-1313 | sed 's/teqo-1313:/teqo-1313-migrator:/')"
|
||||
docker compose --profile maintenance run --rm \
|
||||
-v /srv/archive-reports:/app/data/archive \
|
||||
-v ~/archive-reports:/app/data/archive \
|
||||
teqo-1313-migrate pnpm archive:integrity --only 80,83
|
||||
# 2) reparo do canário (exige TEQO_ENV + confirmação; as 4 S3_* e FLICKR_API_KEY):
|
||||
docker compose --profile maintenance run --rm \
|
||||
-e TEQO_ENV=production -e ARCHIVE_INTEGRITY_CONFIRM=1 \
|
||||
-v /srv/archive-reports:/app/data/archive \
|
||||
-v ~/archive-reports:/app/data/archive \
|
||||
teqo-1313-migrate pnpm archive:integrity --apply --only 80,83
|
||||
# 3) conferir as duas URLs públicas respondendo 200 (antes do lote):
|
||||
# https://jorgesolla1313.com.br/fotos/80/midia e /fotos/83/midia
|
||||
# 4) varredura completa (read-only; ~6,5k downloads no bucket local; sai 1 se achar):
|
||||
docker compose --profile maintenance run --rm \
|
||||
-v /srv/archive-reports:/app/data/archive \
|
||||
-v ~/archive-reports:/app/data/archive \
|
||||
teqo-1313-migrate pnpm archive:integrity
|
||||
# 5) reparo do que a varredura acusou (mesma linha com --apply):
|
||||
docker compose --profile maintenance run --rm \
|
||||
-e TEQO_ENV=production -e ARCHIVE_INTEGRITY_CONFIRM=1 \
|
||||
-v /srv/archive-reports:/app/data/archive \
|
||||
-v ~/archive-reports:/app/data/archive \
|
||||
teqo-1313-migrate pnpm archive:integrity --apply
|
||||
# 6) convergência: re-rodar a varredura; 0 pendências = aceite
|
||||
```
|
||||
|
|
@ -1731,6 +1733,9 @@ varredura mediria o disco efêmero do container); `ALLOW_REMOTE_DB` é recusado.
|
|||
`--concurrency` (default 3) e `--limit`/`--only` são os canários; o recibo traz
|
||||
varridas/ok/ausentes/corrompidas/removidas, e no reparo recuperadas/
|
||||
irrecuperáveis/falhas. A varredura **não** conserta nada: só o `--apply` escreve.
|
||||
O download do original no reparo tem teto de **15 min** — um original grande
|
||||
(~50 MB, ex. panorâmica 7952px) leva minutos no link lento da casa; falha de
|
||||
download é `failed` retentável, nunca rebaixamento.
|
||||
|
||||
Depois de um `--apply` que rebaixou alguma foto, buste a tag pública em um
|
||||
processo que a possui (o write do CLI não revalida o servidor Next):
|
||||
|
|
|
|||
|
|
@ -23,7 +23,13 @@ import { FLICKR_USER_AGENT, isFlickrSourceGone } from './flickrApi.mjs'
|
|||
|
||||
/** A photo original is MBs; the guard only catches a stalled/runaway server. */
|
||||
const PHOTO_DOWNLOAD_MAX_BYTES = 512 * 1024 * 1024
|
||||
const PHOTO_DOWNLOAD_TIMEOUT_MS = 2 * 60_000
|
||||
/**
|
||||
* Flickr originals can pass 50 MB (a 7952px panorama was 54 MB) and the
|
||||
* homeserver's direct egress runs ~260 KB/s — ~3,5 min for that file — so a
|
||||
* 2 min ceiling aborted a legitimate repair (C246 ops, 2026-10-02). 15 min
|
||||
* still catches a stall without capping a slow-but-working link.
|
||||
*/
|
||||
export const ARCHIVE_INTEGRITY_DOWNLOAD_TIMEOUT_MS = 15 * 60_000
|
||||
/** Long edge of the decode proof; the same size the face index feeds the engine. */
|
||||
const DECODE_MAX_EDGE = 1024
|
||||
|
||||
|
|
@ -92,7 +98,7 @@ export const repairArchivePhotoFromSource = async ({
|
|||
url: source.url,
|
||||
destinationPath: filePath,
|
||||
headers: { 'User-Agent': FLICKR_USER_AGENT },
|
||||
timeoutMs: PHOTO_DOWNLOAD_TIMEOUT_MS,
|
||||
timeoutMs: ARCHIVE_INTEGRITY_DOWNLOAD_TIMEOUT_MS,
|
||||
maxBytes: PHOTO_DOWNLOAD_MAX_BYTES,
|
||||
})
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ import { tmpdir } from 'node:os'
|
|||
import { basename, join } from 'node:path'
|
||||
import { afterAll, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { repairArchivePhotoFromSource } from '../../scripts/lib/archiveIntegrityRepair.mjs'
|
||||
import {
|
||||
ARCHIVE_INTEGRITY_DOWNLOAD_TIMEOUT_MS,
|
||||
repairArchivePhotoFromSource,
|
||||
} from '../../scripts/lib/archiveIntegrityRepair.mjs'
|
||||
import { FlickrApiError } from '../../scripts/lib/flickrApi.mjs'
|
||||
|
||||
import { ARCHIVE_PHOTO_JPEG_BYTES } from '../helpers/archivePhotoFixture'
|
||||
|
|
@ -112,6 +115,10 @@ describe('repairArchivePhotoFromSource (C246)', () => {
|
|||
expect(result.sha256).toMatch(/^[0-9a-f]{64}$/)
|
||||
expect(callOrder).toEqual(['source', 'download', 'repair', 'inspect'])
|
||||
expect(basename(vi.mocked(deps.repair).mock.calls[0][1].filePath)).toBe('flickr-123.jpg')
|
||||
// A >50MB Flickr original does not fit the old 2 min ceiling on a slow link.
|
||||
expect(vi.mocked(deps.download).mock.calls[0][0].timeoutMs).toBe(
|
||||
ARCHIVE_INTEGRITY_DOWNLOAD_TIMEOUT_MS,
|
||||
)
|
||||
})
|
||||
|
||||
it('withdraws when Flickr refuses the source (photo gone)', async () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue