Skip to content

feat(horse): adicionar selector HORSE_PROVIDER_NGHTTP2 e hooks de ciclo de vida - #555

Open
freitasjca wants to merge 2 commits into
HashLoad:masterfrom
freitasjca:nghttp2-v2
Open

feat(horse): adicionar selector HORSE_PROVIDER_NGHTTP2 e hooks de ciclo de vida#555
freitasjca wants to merge 2 commits into
HashLoad:masterfrom
freitasjca:nghttp2-v2

Conversation

@freitasjca

@freitasjca freitasjca commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

O que este PR faz

Adiciona uma directiva de compilação opcional ao Horse.pas:

{$DEFINE HORSE_PROVIDER_NGHTTP2}           // selecciona o transporte HTTP/2 nghttp2

Quando a directiva está activa, Horse.pas encaminha TListen, DoStartListenFunc
e DoStopListenFunc para a unidade externa
horse-provider-nghttp2 (https://github.com/freitasjca/horse-provider-nghttp2).
Nenhum provider existente é afectado. Sem a directiva, este ficheiro compila
de forma idêntica ao upstream, tanto em Delphi como em Lazarus/FPC.

Ficheiros alterados

┌─────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┐
│    Ficheiro     │                                           Alteração                                            │
├─────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤
│ src/Horse.pas   │ +49/−3 — tratamento da directiva, guardas de exclusão mútua, hooks do provider                 │
├─────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤
│ README.md       │ +7/−2 — linha do nghttp2 na tabela de providers, correcção do nome da directiva do CrossSocket │
├─────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤
│ README.pt-BR.md │ +7/−2 — idem em PT-BR                                                                          │
└─────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┘

Matriz de testes — Delphi 12.2, upstream/master @ 64e4bbe (2026-08-29)

Todas as falhas listadas são reproduzíveis em upstream/master sem
HORSE_PROVIDER_NGHTTP2. A nossa alteração introduz 0 novas falhas.

┌──────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                          Suite                           │                                                        Resultado                                                         │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Tests.Api.Console (16 testes)                            │ 16/16                                                                                                                 │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Tests.Horse.Commons (8 testes)                           │ 8/8                                                                                                                   │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Tests.Horse.Core.Files / Group / Grpc / MemoryBufferPool │ 26/26                                                                                                                 │
│  / Middleware (26 testes)                                │                                                                                                                          │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Tests.Horse.Core.Param                                   │ 2 falhas pré-existentes — AsCurrency / AsCurrencyDecimalSeparator: separador decimal da máquina (ponto) difere do     │
│                                                          │ esperado pelo teste (vírgula)                                                                                            │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Tests.Horse.Core.Router.Radix + RouterTree (36 testes)   │ 36/36                                                                                                                 │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Tests.Horse.Request.Recycle (8 testes)                   │ 8/8 — inclui os 4 testes WebSocket do PR #550                                                                         │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Tests.Integration.* (excl. ServerLifecycle)              │ 3 erros pré-existentes — ErrorHandling ×2, LifecycleHooks.TestOnRequestAbortingEarly ×1                               │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Tests.Integration.ServerLifecycle                        │ Crash pré-existente do runner em TestBeforeListenExceptionAbortsStartup — excepção da TThread relançada na thread     │
│                                                          │ principal após WaitFor; presente em upstream/master desde 6dc15ef (ancestral de 64e4bbe)                                 │
└──────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

FPC: a suite própria do horse-provider-nghttp2 compila e exercita Horse.pas
com HORSE_PROVIDER_NGHTTP2 activo em FPC trunk 3.3.1 (106/106) e
FPC 3.2.2 (94/94). Os testes unitários do Horse não são executáveis isoladamente
em FPC sem o provider fphttpserver, pelo que os resultados da suite do provider
constituem a prova de compilação da directiva em FPC.

Substitui

PR #545 encerrado. Rebaseado sobre o master actual (64e4bbe), âmbito reduzido
aos 3 ficheiros acima conforme solicitado na revisão do Regys.

@regyssilveira

Copy link
Copy Markdown
Contributor

Obrigado por fechar o #545 e reabrir este PR rebaseado e com escopo bem menor. A estrutura agora está muito mais próxima do que precisamos, mas encontrei alguns pontos a ajustar antes da aprovação:

  1. A descrição apresenta HORSE_PROVIDER_NGHTTP2_REQUIRED, porém essa diretiva não aparece no diff. Remova-a da descrição ou implemente/documente claramente o comportamento pretendido.
  2. A descrição informa que FPC 3.2.2 é suportado, com restrição apenas para gRPC, enquanto os READMEs dizem que FPC trunk 3.3.1 é obrigatório e que 3.2.2 é um bloqueador definitivo. Unifique essa informação conforme a matriz realmente validada.
  3. Adicione uma guarda de exclusão mútua entre HORSE_PROVIDER_NGHTTP2 e HORSE_PROVIDER_IOCP. Sem ela, as duas diretivas podem ser definidas juntas e IOCP vence silenciosamente pela ordem dos {$ELSEIF}.
  4. No ramo FPC, HORSE_APPTYPE_DAEMON e HORSE_APPTYPE_LCL são atualmente ignorados quando nghttp2 está ativo. Implemente as combinações correspondentes ou emita um erro de compilação explícito; uma diretiva de application type não deve ser silenciosamente descartada.
  5. Reduza os READMEs ao escopo do nghttp2. As correções da diretiva CrossSocket, remoção da linha ICS duplicada e inclusão de Prometheus são alterações independentes e devem ficar fora deste PR.
  6. Acrescente à validação os casos negativos das guardas e, em especial, a combinação NGHTTP2 + IOCP e as combinações FPC com application types não suportados.

Com esses ajustes, o PR ficará isolado e pronto para a revisão final da integração opt-in do provider.

Adds the opt-in define HORSE_PROVIDER_NGHTTP2 (and strict-mode alias
HORSE_PROVIDER_NGHTTP2_REQUIRED) to Horse.pas so the nghttp2 HTTP/2
transport can be selected without touching any existing provider code.

horse-provider-nghttp2 supplies TListen, DoStartListenFunc, and
DoStopListenFunc; Horse.pas routes to them when the define is set.
All other providers (Indy, fphttpserver, CrossSocket, mORMot, ICS,
HTTP.sys, epoll, IOCP, host-managed) are completely unaffected. Without
the define this file compiles identically to the upstream original on
both Delphi and Lazarus/FPC.

Supersedes closed PR HashLoad#545.
@freitasjca

freitasjca commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Obrigado pela revisão e pelas indicações dadas.

Todos os ajustes foram aplicados e enviados (e55fb03, rebaseado sobre 0bc2ab7).

  1. HORSE_PROVIDER_NGHTTP2_REQUIRED removida da descrição — a diretiva não estava implementada.

  2. Matriz unificada: FPC 3.2.2 e trunk 3.3.1 ambos suportam o transporte HTTP/2; apenas gRPC exige o trunk 3.3.1 (compile em 3.2.2 com -dHORSE_NGHTTP2_NO_GRPC). A frase "3.2.2 é um bloqueador definitivo" era texto obsoleto e foi removida — a descrição já refletia a matriz validada.

  3. Guarda de exclusão mútua adicionada. Confirmado exatamente como descrito: HORSE_PROVIDER_IOCP é testado antes de HORSE_PROVIDER_NGHTTP2 em todas as cadeias de seleção, então as duas diretivas juntas compilavam sem aviso e produziam um binário IOCP.

  4. HORSE_APPTYPE_DAEMON e HORSE_APPTYPE_LCL agora emitem {$MESSAGE FATAL} sob nghttp2 no FPC, indicando a unit ausente e as alternativas. Optei por FATAL e não ERROR porque as diretivas ficam dentro da cláusula uses: a compilação precisa parar ali, senão o nome de unit ausente gera erros de sintaxe não relacionados.

  5. READMEs reduzidos ao escopo do nghttp2 — agora 3 adições e 0 remoções em cada arquivo. A correção da diretiva CrossSocket, a remoção da linha ICS duplicada e a linha do Prometheus sairão em PR separado.

  6. Casos negativos implementados e executados em FPC trunk 3.3.1:

── 19 compile-guard negative cases (Horse.pas) ─────────────────────────
PASS NGHTTP2 + IOCP rejected (would otherwise build IOCP silently)
PASS NGHTTP2 + APPTYPE_DAEMON rejected on FPC (no FPC.Daemon unit)
PASS NGHTTP2 + APPTYPE_LCL rejected on FPC (no FPC.LCL unit)
PASS CONTROL: NGHTTP2 alone still compiles (probe is valid)

Cada teste verifica a mensagem específica, não apenas o código de saída — só o status passaria em qualquer quebra não relacionada e continuaria passando se a guarda fosse removida.

Ressalva importante: esses testes vivem no repositório do provider (horse-provider-nghttp2, samples/tests/build-fpc.sh, estágio 19), não neste PR — o diff aqui não contém teste algum. Testes de guarda são de tempo de compilação, então não são expressáveis em DUnitX; precisariam de um script próprio na suíte do Horse.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants