52 lines
7.8 KiB
Markdown
52 lines
7.8 KiB
Markdown
# Consulta de liquidação SGF separada dos bloqueios de escrita
|
|
|
|
02/11/2026 — `SGF-SETTLEMENT-READ-ISOLATION-SIM-v1`. Continuação local sintética do [histórico paginado](SGF_SETTLEMENT_PAGED_READ_DELIVERY.md). Remove da consulta paginada SGF os bloqueios de escrita da empresa/utilizador; preserva a autoridade, os bloqueios e a conferência actual dos comandos.
|
|
|
|
## Implementação e contrato
|
|
|
|
O núcleo aceita uma autorização opcional e específica para a leitura paginada de pagamentos. O adaptador SGF fornece a mesma verificação existente de actor autenticado, contexto exacto, pessoa e direitos `view/payments_view`, usando o ramo sem bloqueio. Não se criou uma concessão paralela nem se concederam direitos novos.
|
|
|
|
`SupplierSettlements::listingPage()` usa esse callback apenas na consulta. `command()` conserva o callback original de escrita; `listing()` e construtores sem o argumento novo conservam também a autorização anterior. O callback de leitura nunca autoriza uma decisão. O pacote instalado da composição nativa não foi substituído ou activado, e essa composição não optou automaticamente pelo novo contrato.
|
|
|
|
Quando é dona da transacção, a consulta paginada inicia `REPEATABLE READ READ ONLY`. O controlador SGF inicia igualmente uma única transacção desse tipo para a leitura completa de pagamentos, posições documentais, propostas exactas e referências. Todas essas listas partilham o mesmo instantâneo do pedido. Uma leitura dentro de uma transacção já existente participa nela; não tenta mudar o isolamento depois de já haver consultas. O percurso HTTP efectivo foi verificado como transacção própria só de leitura.
|
|
|
|
Não se alteraram os cálculos de principal, afectações, reversões ou saldo. As confirmações continuam a obter os bloqueios e a conferir os factos/versões/ciclo actuais. A identidade capturada na construção do motor é comparada novamente na consulta; direitos revogados, pessoa alterada ou actor trocado não são herdados da construção anterior.
|
|
|
|
## Concorrência efectivamente observada
|
|
|
|
Reutilizada a base sintética própria da entrega anterior, com 1.000 pagamentos, sem reset ou novas operações persistentes. Uma transacção principal bloqueou a linha de `companies` e preparou/confirmou, sem commit, uma reversão adicional pelos comandos comuns. Dentro dessa transacção, o montante por afectar passaria de 0,41 para 0,42 MZN.
|
|
|
|
Três processos PHP/ligação independentes exercitaram os percursos:
|
|
|
|
| Percurso | Enquanto o escritor mantém o bloqueio | Depois da libertação |
|
|
|---|---|---|
|
|
| Consulta paginada pelo controlador SGF | Termina em **357,581 ms**, sem `FOR UPDATE`, com `repeatable read/read_only=on`; vê 0,41 MZN e os nove eventos confirmados | Nenhuma alteração de dados |
|
|
| Consulta integral anterior, pela mesma autorização de escrita | Aguarda em `companies FOR UPDATE` | Conclui com 0,41 MZN; conserva os dois bloqueios de escrita anteriores |
|
|
| Confirmação de proposta sintética de afectação | Aguarda em `companies FOR UPDATE` | Revalida e conclui; a repetição da mesma chave recupera a mesma decisão, com exactamente uma decisão e uma afectação para o destino |
|
|
|
|
`pg_blocking_pids` e `pg_stat_activity` identificaram a cadeia até à transacção principal. Um processo esperava no `transactionid`; o outro podia esperar no `tuple`, atrás do primeiro concorrente. A ordem variou com a chegada dos processos. O diagnóstico inicial exigia incorrectamente que ambos tivessem o pai como bloqueador directo; a prova final segue também a ligação indirecta da fila, sem confundir essa espera com outro recurso ou outra autorização.
|
|
|
|
A consulta nova terminou enquanto **ambos os outros processos ainda estavam bloqueados**. Não observou a reversão por confirmar. O pai libertou o bloqueio por rollback; a confirmação posterior decorreu dentro de outra transacção externa, igualmente revertida depois de conferir o resultado e a repetição. Assim, a proposta sintética de afectação original mantém-se pendente e não foi efectuada qualquer decisão de pagamento histórico importado.
|
|
|
|
Os tempos totais dos processos antigos incluem a espera, e a consulta integral lê um universo diferente do foco paginado. **Não são um comparativo controlado de velocidade por página**, throughput ou capacidade. O resultado demonstrado é a independência da consulta perante esse bloqueio de linha, com escrita ainda serializada e revalidada.
|
|
|
|
## Provas dirigidas e recuperação
|
|
|
|
- Quatro cenários novos, **23 asserções**: transacção própria coerente/só de leitura; ausência de `FOR UPDATE`; modo de leitura não persiste na ligação; contrato antigo mantém os dois bloqueios; callback de leitura não autoriza comandos; direitos/pessoa/actor alterados recusados.
|
|
- Reutilizados os SHA-256 das quatro janelas de 25/100 e da posição original da entrega anterior. Igualdade confirmada; os benchmarks anteriores não foram repetidos. Não se acrescentam novas medições de memória, índices ou volumes nesta entrega.
|
|
- Tentativa injectada de inserir um evento dentro da consulta: PostgreSQL recusa com `25006`, a transacção é desfeita e a leitura seguinte recupera normalmente. Nenhum evento foi gravado.
|
|
- **11 verificações HTTP reais**, dirigidas à mudança: ausência de autenticação401, JSON e HTML com isolamento/só-leitura e zero `FOR UPDATE`, posição original, contexto obsoleto409, foco indevido403, confirmação recusada ao leitor403, CSRF419 e `no-store`. A instrumentação é exclusivamente do router QA privado. Servidor loopback8047 encerrado; não houve navegador.
|
|
- Pós-ensaio só de leitura confirmou o fingerprint financeiro integral anterior: fontes, propostas, obrigações, pagamentos, decisões, afectações, reversões, eventos, comandos e direitos iguais. A decisão da proposta pendente continua ausente. Sequências podem avançar pelas inserções revertidas; não foram repostas para ocultar o ensaio.
|
|
|
|
Manifesto: [resultados, condições e hashes](proofs/sgf-settlement-read-isolation-20261102.json). Inclui conferência dos hashes de **todos os artefactos privados registados na prova anterior**, sem a sobrescrever. Execuções diagnósticas não são contadas como aprovadas. A comparação inicial entre posições foi corrigida para comparar os valores serializados, em vez da identidade de objectos PHP distintos; o cálculo não mudou.
|
|
|
|
Reprodução dirigida com PHP fixado: `scripts/payable-history-sgf-proof.php <settings QA privado> settlement-read-race`, `settlement-read-cases` ou `settlement-read-post`. Cada prova concluída é preservada, sem sobrescrita automática. HTTP: `scripts/settlement-read-http.mjs <tag>`. Consolidação sem repetir testes: `scripts/summarize-settlement-read.mjs <tag>`. Guardas exigem a base/role próprias do cluster55439; credenciais, sessões, entradas e logs permanecem privados.
|
|
|
|
## Limites preservados
|
|
|
|
Os direitos e os factos são conferidos no instantâneo de cada pedido. Uma revogação que ocorra depois desse instantâneo será observada pelos pedidos seguintes; não há fotografia congelada entre páginas visitadas por uma pessoa. As decisões continuam a conferir o estado actual no seu percurso de escrita.
|
|
|
|
Leitura normal continua sujeita aos recursos e bloqueios gerais da base, incluindo DDL; não se garante ausência absoluta de espera. Não foi medida carga sustentada, contenção entre muitas empresas ou capacidade de implantação. A prova não altera o conjunto de medições anteriores de documentos ou pagamentos nem autoriza instalar índices.
|
|
|
|
Sem novas rotas operacionais, direitos, migrações no destino, activação de Compras, pagamentos reais, fornecedor histórico SGF vivo, cutover financeiro, reconciliação, contabilidade, publicação ou checkpoint. Seis registos protegidos, cache bloqueada, demonstrações e trabalho alheio intactos. Revisão visual e implantação permanecem pendências separadas.
|