Files
SGF/docs/MODULE_ASSOCIATION_LOAD_CONSOLIDATION.md
2026-11-02 20:29:34 +02:00

21 KiB
Raw Permalink Blame History

Fila de associações — consolidação de carga, concorrência e HTTP

02/11/2026. A optimização está implementada localmente. A listagem usa leitura conjunta da página e das suas dependências em describePage/pageStates, com lotes limitados, sem materializar o universo. A projecção posterior pageColumns selecciona metadados e referências em vez dos corpos completos. Prévia e confirmação continuam a obter e revalidar o estado completo actual. Código: ModuleAssociationReview.php. Esta passagem acrescenta provas e documentação; não altera esse código funcional.

Cobertura conferida e medições em falta

Consolidação das três entregas, com conferência dos hashes das provas e das fontes actuais do serviço e controlador. Existem 24 combinações obrigatórias: 3 volumes × 4 áreas × páginas de 25/100, todas com resultados medidos para A/B/C, mais 9 cenários de filtros. Não falta nenhuma combinação dessa comparação da leitura conjunta. Não se abriu ligação a qualquer base, nem se executou nova medição ou suite nesta consolidação. Foram reutilizadas as provas válidas.

Há 13 tentativas da baseline limitadas pelo orçamento de 15 s; constituem resultados censurados, não medições completas nem combinações nunca executadas. A tabela mantém esses limites explícitos, sem inventar medianas ou rácios de ganho. Prolongar apenas a baseline mudaria as condições; não se repetiram as experiências válidas para obter números completos da versão antiga.

A comparação nos três volumes mede o incremento de leitura conjunta anterior à projecção, com a fonte B/C identificada abaixo. A versão actual com projecção tem prova própria de 10 000 registos por área, documentos de 100 linhas e duas dimensões de descrição; não foi medida numa nova matriz completa de 1 000/5 000/10 000 contra a baseline original. Não se fundiram essas experiências nem se apresentam valores de B como sendo da fonte projectada actual. Essa matriz adicional não é necessária para demonstrar o ganho isolado da leitura conjunta e não foi repetida nesta consolidação.

Inventário verificável da cobertura, métricas por combinação e hashes. O verificador scripts/consolidate-association-evidence.mjs lê apenas fontes e provas locais, valida as 24 combinações e rejeita lacunas ou alterações de hash; não executa SQL.

Espera da confirmação: causa e resultado após libertação

A prova anterior atingiu lock_timeout=1000ms (SQLSTATE 55P03, 1 044,222 ms) porque a primeira transacção foi deliberadamente mantida aberta. A nova prova observou a consulta sobre companies com FOR UPDATE, o PID da primeira transacção em pg_blocking_pids e a espera Lock / transactionid / ShareLock em pg_stat_activity/pg_locks. É serialização da confirmação por empresa; o limite não surgiu da leitura conjunta da auditoria. Pode também serializar confirmações de registos diferentes da mesma empresa; esse volume de escritores não foi medido.

Em quatro cenários novos, a primeira transacção foi libertada depois de observar a espera real e aguardar mais 200 ms. O segundo processo tinha limite de bloqueio de 8 s exclusivamente para esta prova. Os tempos abaixo incluem espera e execução, não representam latência normal nem tempo puro após desbloqueio.

Cenário Libertação da primeira Segunda confirmação Tempo total ms Versão do registo final Eventos de decisão após repetição
rollback_then_complete rollback 200 352,39 1 1
commit_then_stale_revision commit 409 338,39 1 1
commit_then_same_token commit 200 (repetição) 333,37 1 1
commit_record_change_then_stale_version commit 409 335,55 2 0

Após rollback, a segunda decisão gravou exactamente um evento. Após commit de outra decisão, o token preparado antes da espera recebeu 409 por revisão de associações desactualizada, mesmo mantendo versão documental 1; nova prévia foi possível. O mesmo token da decisão vencedora recebeu sucesso idempotente e o mesmo identificador de evento. Quando a versão documental mudou para 2 durante a espera, o token da versão 1 recebeu 409, sem decisão; uma prévia da versão 2 foi possível. As repetições não acrescentaram eventos. Os estados de sucesso/409 do segundo processo são resultados do serviço; as repetições e novas prévias foram também verificadas pela API em processo. A apresentação HTTP do limite foi posteriormente implementada e provada separadamente, conforme a secção seguinte.

Prova de libertação reutilizada: 1 teste / 79 asserções, sem falhas ou erros, mais quatro trabalhadores concluídos. Prova e resumo com hashes. A primeira tentativa desta prova concluiu os quatro cenários mas falhou na comparação final da auditoria por exceder 65 535 parâmetros SQL; corrigiu-se apenas o auxiliar de preservação para IDs inteiros capturados. A execução acima repetiu esta prova afectada e passou; não se repetiram as matrizes ou suites válidas.

Tratamento HTTP entregue e provado

O controlador administrativo existente passou a traduzir exclusivamente SQLSTATE 55P03 em 423 / association_busy, para prévia e confirmação, depois do rollback do serviço. A resposta contém apenas mensagem administrativa e código, com Cache-Control: no-store, sem SQL/bindings ou stack trace. Não foram alterados o prazo de espera, os direitos ou o serviço de decisão; não há repetição automática. Outras excepções mantêm o tratamento existente, e mudanças de estado continuam a produzir 409.

Pedido limitado Tempo total com espera diagnóstica ms Resposta Libertação e recuperação posterior
Confirmação 1086,658 423 Rollback da primeira; repetição manual 200 e repetição idempotente
Confirmação 1093,136 423 Commit da primeira; token antigo 409 e nova prévia 200
Prévia 1083,944 423 Rollback da primeira; nova prévia 200, confirmação e repetição idempotente

Em cada caso foi observado o bloqueador real, configurando 1 s apenas na ligação do trabalhador de prova. A contagem após libertação confirmou ausência de decisão parcial do pedido limitado; após recuperação ficou exactamente um evento por cliente, sem duplicação. Estes tempos incluem a espera deliberada, não latência normal.

1 teste / 54 asserções, mais três trabalhadores aprovados; 13 testes / 232 asserções da fila afectados pela alteração do controlador também aprovados. Estes últimos foram repetidos na entrega HTTP por haver alteração funcional, não nesta consolidação. A prova anterior de navegação e as matrizes mantiveram-se válidas, sem repetição. Não somar asserções de suites sobrepostas como cobertura distinta.

Entrega HTTP · Prova · Testes e hashes. Controlador actual SHA-256 6c16481f7e3f4355ba60ca22bc67385ec3b3113b4784e5d9f57025618e1735a9. A apresentação foi provada pelo kernel HTTP em processo; navegador, servidor HTTP de implantação e rede permanecem fora da prova.

Comparação A/B/C: leitura conjunta e índices separados

Medições já válidas, reutilizadas sem nova execução. A: checkpoint 340f3bb, consultas por registo; B: leitura conjunta, sem índices experimentais, antes da projecção posterior; C: mesmo B com dois índices experimentais de auditoria. Portanto A→B mede a leitura conjunta e B→C mede separadamente os índices. Não atribuir ao código actual exactamente os tempos de B: a projecção tem outra medição e hash abaixo.

Mesma fixture imutável em cada volume, 1 000/5 000/10 000 por cada uma das quatro áreas, dependências incluídas; três repetições, ordem A/B alternada, C sobre os mesmos dados, kernel e buffers aquecidos. Valores: mediana de tempo; consultas por pedido completo; máximo de memória PHP usada incremental acima do início do pedido, em KiB, sem incluir PostgreSQL ou memória total do processo. “limite” significa tentativa interrompida pelo orçamento diagnóstico de 15 s, sem mediana/consultas/memória comparáveis; não é um valor de 15 s nem um ganho calculável. Na prova completa foram 258 leituras medidas concluídas e 13 tentativas limitadas; respostas completas comparáveis idênticas.

Cada célula contém A / B / C. A memória em B pode aumentar face a A, por conservar o conjunto da página; a redução de consultas não implica redução de memória.

Registos por área Área / filtro Página Tempo ms A/B/C Consultas A/B/C Memória incremental KiB A/B/C
1000 Clientes / all 25 1986,50 / 36,77 / 10,66 185 / 11 / 11 86,50 / 100,29 / 100,13
1000 Clientes / all 100 7407,37 / 29,77 / 12,85 710 / 11 / 11 158,61 / 254,37 / 254,21
1000 Serviços / all 25 1924,42 / 30,09 / 10,81 185 / 11 / 11 86,55 / 99,55 / 99,39
1000 Serviços / all 100 7778,43 / 31,96 / 11,90 710 / 11 / 11 158,70 / 253,59 / 253,45
1000 Rascunhos serviço / all 25 3905,95 / 77,23 / 16,65 435 / 19 / 19 116,95 / 221,35 / 221,22
1000 Rascunhos serviço / all 100 limite / 77,02 / 22,16 limite / 19 / 19 limite / 744,63 / 744,50
1000 Rascunhos facturação / all 25 5014,74 / 96,21 / 19,61 560 / 23 / 23 131,74 / 294,41 / 294,28
1000 Rascunhos facturação / all 100 limite / 100,60 / 28,94 limite / 23 / 23 limite / 1037,20 / 1037,06
1000 Clientes / pending 25 1974,80 / 100,45 / 86,03 185 / 11 / 11 85,87 / 96,77 / 96,63
1000 Clientes / associated 25 2034,10 / 107,24 / 34,23 185 / 11 / 11 92,58 / 112,45 / 112,33
1000 Clientes / removed 25 2721,26 / 754,12 / 78,34 185 / 11 / 11 88,05 / 107,75 / 107,61
5000 Clientes / all 25 6295,36 / 97,22 / 18,45 185 / 11 / 11 86,75 / 100,30 / 100,14
5000 Clientes / all 100 limite / 87,01 / 19,76 limite / 11 / 11 limite / 254,63 / 254,47
5000 Serviços / all 25 5238,39 / 92,19 / 17,11 185 / 11 / 11 86,80 / 100,36 / 100,20
5000 Serviços / all 100 limite / 77,98 / 18,13 limite / 11 / 11 limite / 254,70 / 254,55
5000 Rascunhos serviço / all 25 10553,09 / 216,02 / 36,97 435 / 19 / 19 117,20 / 221,60 / 221,47
5000 Rascunhos serviço / all 100 limite / 232,94 / 44,38 limite / 19 / 19 limite / 744,88 / 744,75
5000 Rascunhos facturação / all 25 13947,25 / 377,18 / 33,66 560 / 23 / 23 132,33 / 294,41 / 294,28
5000 Rascunhos facturação / all 100 limite / 322,13 / 65,66 limite / 23 / 23 limite / 1037,20 / 1037,06
5000 Clientes / pending 25 7236,64 / 578,25 / 104,08 185 / 11 / 11 85,87 / 96,77 / 96,63
5000 Clientes / associated 25 7045,59 / 362,62 / 329,05 185 / 11 / 11 92,58 / 112,45 / 112,33
5000 Clientes / removed 25 6394,64 / 679,37 / 409,55 185 / 11 / 11 88,05 / 107,75 / 107,61
10000 Clientes / all 25 9683,04 / 156,32 / 13,88 185 / 11 / 11 86,75 / 100,30 / 100,14
10000 Clientes / all 100 limite / 203,09 / 14,52 limite / 11 / 11 limite / 254,63 / 254,47
10000 Serviços / all 25 9385,15 / 117,18 / 11,66 185 / 11 / 11 86,55 / 99,55 / 99,39
10000 Serviços / all 100 limite / 109,77 / 14,87 limite / 11 / 11 limite / 253,59 / 253,45
10000 Rascunhos serviço / all 25 limite / 333,79 / 20,32 limite / 19 / 19 limite / 220,98 / 220,85
10000 Rascunhos serviço / all 100 limite / 399,87 / 26,89 limite / 19 / 19 limite / 744,27 / 744,13
10000 Rascunhos facturação / all 25 limite / 592,80 / 28,73 limite / 23 / 23 limite / 294,05 / 293,91
10000 Rascunhos facturação / all 100 limite / 451,13 / 35,65 limite / 23 / 23 limite / 1036,83 / 1036,70
10000 Clientes / pending 25 limite / 2553,13 / 113,84 limite / 11 / 11 limite / 96,77 / 96,63
10000 Clientes / associated 25 9377,31 / 521,51 / 254,95 185 / 11 / 11 92,58 / 112,45 / 112,33
10000 Clientes / removed 25 9973,28 / 1290,76 / 292,74 185 / 11 / 11 88,05 / 107,75 / 107,61

Métricas brutas, incluindo picos PHP absolutos, tempos SQL, amostras e hashes: comparação. Método, planos, índices e recusas de acesso. Os dois índices (ligações por módulo e revisão por registo) foram criados apenas no ensaio sintético e desfeitos por rollback/savepoint; nenhum índice no destino.

Código actual: projecção e documentos com muitas dependências

A fase posterior comparou B com a projecção actual, mantendo 10 000 registos por área e 100 linhas por rascunho, páginas 25/100, descrições de 128/1 000 bytes. Foram 132 leituras completas, 44 cenários, respostas equivalentes. A projecção reduziu a memória, mas não acelerou todas as leituras sem índice. Para descrições de 1 000 bytes:

Área / página Tempo ms antes projecção / actual sem índice / actual só índice revisão / actual par Memória incremental MiB antes / actual
Serviço / 25 668,119 / 728,558 / 97,487 / 225,676 8,28 / 4,21
Serviço / 100 2150,980 / 2861,608 / 341,479 / 408,455 32,42 / 16,65
Facturação / 25 815,219 / 905,073 / 111,725 / 127,118 11,55 / 4,85
Facturação / 100 2720,541 / 2481,159 / 374,043 / 368,403 45,49 / 19,23

Consultas: serviço 27/57 e facturação 31/61, páginas 25/100; o crescimento decorre dos lotes das dependências (até 10 000 serviços na página), não do carregamento de todo o universo. Índice de revisão: 13,73 MiB; par: 30,50 MiB. O segundo índice não mostrou benefício consistente; não foi recomendado/aplicado automaticamente. Experiências desfeitas apenas na base sintética. Relatório e provas desta fase.

Proveniência SHA-256 do serviço: A 44a2c75d6a2ecaddc151b3c92175324e15ca4e2664a87a4d50c093913adb4114; B/C 6df1a85af8ea3112ff8e61741408158cd0444944cc3e0b407ad5bd4ad8043361; projecção actual e nova prova de libertação b901bccc73a59e80d98d32a56532e9300a55ba9a216e5ac5a0ce84d78f976397. A confirmação/prévia não foram alteradas pela optimização.

Concorrência de leitura e equivalência preservadas

Mantêm-se válidas 440 leituras completas, até quatro identidades/processos com sobreposição efectivamente observada: 420 da matriz e 20 durante confirmação sem commit. Página 25, 3 000 por área, rascunhos com 100 linhas de 1 000 bytes. Todas corresponderam aos hashes autorizados; os leitores viram o estado anterior enquanto a decisão não tinha commit. Não foram repetidas.

Com quatro processos, clientes: P50/P95 amostral 37,990/60,810 ms sem índice, 14,790/21,402 ms com revisão; facturação: 429,457/495,430 ms sem índice, 102,861/121,342 ms com revisão. Consultas 11/31, memória incremental máxima aproximada 0,09/4,85 MiB por pedido. Os percentis descrevem amostras pequenas (15/30/60 pedidos); não constituem SLA. O índice desta prova entre processos foi gravado só na regressão para ser visível, depois removido explicitamente, com catálogo anterior igual. Ondas, tempos e limites.

Preservam-se também as provas válidas afectadas: 21 testes / 322 asserções, equivalência de filtros, ordenação, paginação, isolamento e recusas, versões/dependências, prévia, confirmação, falha e recuperação; ensaios separados de planos e acessos documentados na entrega. Não foram repetidos por não haver alteração funcional nesta continuação.

Gargalos que persistem e correcção mínima proposta

Leitura SQL: a leitura conjunta eliminou as consultas à auditoria por cada registo da página, mas os filtros de estado e as contagens conservam EXISTS/NOT EXISTS correlacionados, e a agregação de estados ainda tem de procurar/ordenar eventos da auditoria. Sem índice adequado ao âmbito/chaves JSON, continuam varrimentos e trabalho proporcional ao histórico. Em 10 000 clientes, o filtro de pendentes ainda demorou 2 553,134 ms na variante B sem índice, contra 113,836 ms com o par; essa melhoria não deve ser atribuída apenas ao batching. Os planos e a experiência posterior distinguindo revisão/par sustentam o candidato mais pequeno, não a criação automática de ambos.

Proposta mínima: usar como candidato apenas o índice parcial de revisão já experimentado, sem nova tabela, cache de decisões ou reescrita do circuito. Definição reproduzida para revisão, não executada nesta passagem e não aplicada no destino:

CREATE INDEX sgf_qa_assoc_revision
ON identity_audit
  (tenant_id, company_id, (details->>'area'), (details->>'record_id'), id DESC)
WHERE action IN
  ('module.record.associated', 'module.record.disassociated', 'module.record.reviewed');

Este é o nome/DDL do candidato QA, não uma migração de produção. A prova isolada da projecção mediu cerca de 13,73 MiB para esse índice; o par ocupou 30,50 MiB e não mostrou ganho consistente. Antes de qualquer implantação, falta validar plano, custo de escrita/manutenção, criação/recuperação e condições do destino. Se os filtros ainda forem lentos com o índice, o incremento seguinte mínimo será calcular os estados por âmbito numa relação SQL comum reutilizada na contagem/página, preservando a semântica da última associação/retirada por módulo e separando-a da revisão. Essa reescrita não está implementada nem validada; os dados actuais não justificam fazê-la antes de avaliar o candidato menor.

Documentos com muitas dependências: o custo residual de memória/consultas cresce com a página e o número de referências reais (até 10 000 serviços), mesmo após projectar o corpo documental. A projecção já reduziu o pior caso medido de 45,49 para 19,23 MiB. Um índice não elimina esse custo em PHP; não declarar que o índice resolve memória ou renderização. A página de 25 já disponível é a opção menos pesada no ensaio; não se alterou o limite de 100 nem se truncaram dependências silenciosamente. Uma eventual consulta progressiva das dependências exigiria outro incremento e prova de equivalência.

Confirmações: o FOR UPDATE da empresa serializa os escritores e foi mantido para preservar a revalidação de contexto/permissões. O 423 já entregue melhora a resposta a um limite, mas não remove o bloqueio nem aumenta o débito. Não remover ou estreitar esse lock sem provar corridas com a administração de acessos. O mínimo operacional pendente é definir um orçamento de espera coerente com o servidor HTTP e manter repetição manual/revalidação; não se escolheu ou aplicou um prazo real por consequência destes testes.

Preservação e pendências separadas

A execução de libertação anteriormente concluída verificou fisicamente sgf_tempo_test / sgf_test_runner / porta 55439 / cluster sgf_modular_regression_2576427d1939. Usou quatro clientes e âmbito novos, exclusivamente de regressão, gravados para visibilidade entre processos e retidos com manifesto privado. A primeira tentativa também deixou a sua pequena fixture sintética nesta base; não se apagou nem reinicializou a base. A execução válida verificou hashes dos registos QA anteriores e igualdade do catálogo de índices. Tokens, contexto e manifestos privados não integram estas provas públicas.

Os seis registos protegidos, a demonstração 8039, o SGF local, a cache bloqueada, provas válidas e trabalho alheio foram preservados; não se abriu ligação ao destino nesta prova. Sem novos índices, direitos públicos, activação de Compras, publicação ou checkpoint. O auxiliar de preservação foi corrigido, não a aplicação.

Capacidade de implantação não validada. Estes ensaios locais usam kernel HTTP em processo e trabalhadores PHP; não medem navegador, login/MFA, rede/TLS, servidor HTTP implantado, carga sustentada, vários escritores ou recursos completos do servidor. Faltam condições, orçamento de memória, índices/planos e política de espera/repetição próprios do destino. A revisão visual permanece separada e pendente, sem repetir a via de navegador bloqueada.

Nesta consolidação não se alterou código da aplicação, não se executou SQL nem se repetiram testes. Conferiram-se as fontes e os hashes das provas anteriores e produziu-se o inventário de cobertura. Revisão visual: pendente, incluindo a apresentação de páginas com muitas dependências e mensagens ao utilizador. Capacidade de implantação: pendente, com as provas operacionais próprias enumeradas acima. Uma pendência não é pré-condição para documentar a outra nem prova de que esteja concluída. Os seis registos e a cache não foram acedidos ou alterados.