4.8 KiB
Impl: E2E-ADMIN-LOGIN-LOCK — Serializar o login de UI do beforeEach do admin e2e
Status: aprovado (pendente gate humano) Atualizado em: 2026-08-23 Issue: #805 Intenção: body da Issue #805 (dívida capturada no #760) Appetite restante: ~0,25 dia
Leitura da intenção
- Outcome: O
beforeEach(UI form login) detests/e2e/admin.e2e.spec.tsdeve serializar com o mesmo advisory lock727001queadminHeaders(REST) já usa, para eliminar a janela de colisão worker(admin UI) × worker(adminHeaders lock) que pode perder sessão → 403 no e2e full. - O que NÃO negociar: não trocar o login UI por API login (o spec testa genuinamente o formulário); não serializar o projeto inteiro/workers; não tocar o retry
campaignHomePixel403→relogin. - O que reavaliar: além do
beforeEach, o spec tem dois logins REST inline não-lockados (linhas 50 e 152) — mesma classe de corrida; rotear poradminHeadersfecha o spec inteiro.
Abordagem recomendada
Extrair um helper withAdvisoryLock + chave compartilhada 727001; serializar o login() UI; e rotear os logins REST inline do spec por adminHeaders.
flowchart LR
subgraph helpers
advisoryLock.ts[advisoryLock.ts<br/>ADMIN_LOGIN_LOCK_KEY=727001<br/>withAdvisoryLock()]
login.ts[login.ts<br/>UI form + withAdvisoryLock]
adminApi.ts[adminApi.ts<br/>adminHeaders usa withAdvisoryLock]
end
subgraph spec
admin.e2e.spec.ts[beforeEach login() UI<br/>+:50,:152 REST via adminHeaders]
end
advisoryLock.ts --> login.ts
advisoryLock.ts --> adminApi.ts
login.ts --> admin.e2e.spec.ts
adminApi.ts --> admin.e2e.spec.ts
Opções consideradas: A (helper + chave única + owner login() + rotear inline do spec) | B (duplicar bloco pg dentro de login()) | C (envolver login() no beforeEach) | D (não serializar inline REST do spec)
Recomendação: A — porque a chave precisa ser a mesma nos dois caminhos (UI × API fecham a corrida entre si); o helper evita twin do boilerplate pg; o lock dentro de login() deixa o owner do concern coberto para futuros chamadores; e os dois logins REST inline do spec são a mesma classe de corrida.
Rejeitadas: B (cria twin; o padrão já vive em adminHeaders); C (empurra responsabilidade para o spec, owner descobreto); D (mantém janela aberta dentro do próprio spec).
Componentes / mudanças
tests/helpers/advisoryLock.ts(novo):ADMIN_LOGIN_LOCK_KEY = 727_001+withAdvisoryLock<T>(key, fn)— abreClient({ connectionString: process.env.DATABASE_URL }),pg_advisory_lock($1)antes, unlock+end nofinally(.catchno unlock, espelhandoadminApi.ts:37-40).tests/helpers/adminApi.ts: refatoraradminHeaderspara usarwithAdvisoryLock(ADMIN_LOGIN_LOCK_KEY, ...); remover const local:8e o client inline.tests/helpers/login.ts: envolver a submissão do formulário comwithAdvisoryLock(ADMIN_LOGIN_LOCK_KEY, ...)emtry/finally(lock antes do submit, release após dashboard renderizado, garantido mesmo se asserção falhar).tests/e2e/admin.e2e.spec.ts: substituir os doisrequest.post(.../api/users/login)inline (linhas 50-55, 152-157) poradminHeaders(request, baseURL); importar de../helpers/adminApi.- Migration: sem migration.
- Access / Consent: n/a (teste).
- UI: n/a (teste).
Fases verificáveis
- Fase 1 — Helper: criar
advisoryLock.ts; refatoraradminApi.ts. →pnpm typecheck,pnpm lint. - Fase 2 — Serializar UI login: envolver
login.tscomwithAdvisoryLock. →pnpm typecheck,pnpm lint. - Fase 3 — Inline REST do spec: rotear por
adminHeaders; remover bloco inline órfão. →pnpm lint. - Fase 4 — Verificação (OPS72): rodar admin e2e isolado e o full com 4 workers; confirmar ausência de 403 por sessão perdida.
Rabbit holes / Não escopo (engenharia)
- NÃO trocar UI login por API login; NÃO serializar projeto/workers; NÃO tocar
campaignHomePixelretry. - Fora:
frontend.e2e.spec.ts:613(shadow local não-lockado deadminHeaders) — próprio plano, não agravado por este fix. - Sem migration/schema/UI; só
tests/helpers/*etests/e2e/admin.e2e.spec.ts.
Riscos e mitigação
- Release do lock: lock fica preso até o dashboard renderizar;
finallygarante release em falha de asserção (evita travar o próximo worker). - Timing novo:
login()abre conexão pg por login; impacto mínimo (dezenas por run). withAdvisoryLocké só p/ serialização de teste_test— nunca promover a lock de produção.
Aceite de engenharia
- Aceite de produto da intenção ainda coberto (UI login serializado na mesma chave)
- Invariantes AGENTS/engineering-standards (reusa padrão existente; sem twin)
- Testes de domínio: verificação via e2e admin isolado + full-4-workers