Recentemente, o framework Horse recebeu atualizações muito importantes para suporte a gRPC utilizando o transporte nativo HTTP/2. Desde então, muitos desenvolvedores que testaram a tecnologia com Node.js ou outras linguagens começaram a se perguntar: como estruturar um cliente robusto em Delphi?
Desenvolver aplicações móveis (FMX) ou desktop integradas com gRPC exige atenção a conceitos importantes de arquitetura de software, como resiliência de rede, gerenciamento de threads e estratégias offline. Neste artigo, vamos responder às principais dúvidas sobre reconexão automática, keepalive, ciclo de vida de conexões e como aplicar Offline First de maneira eficiente.
1. Como funciona a resiliência no gRPC? (Reconexão e Keepalive)
Uma dúvida comum ao migrar de APIs REST tradicionais para gRPC é o comportamento da conexão caso a internet oscile. No ecossistema gRPC, a resiliência é dividida em duas partes:
- Reconexão Automática (Client-Side): O restabelecimento da conexão é de responsabilidade do cliente gRPC. Bibliotecas maduras (como o
@grpc/grpc-jsdo Node.js ou os clients gerados para Delphi) tratam as quedas de rede de forma transparente através de políticas de backoff exponencial. Se a rede cair, o cliente tentará reconectar em background antes de disparar a próxima chamada. - Keepalive (Ping/Pong no HTTP/2): O servidor HTTP/2 do Horse possui suporte nativo completo ao frame
PING. Quando o cliente gRPC envia frames de verificação de saúde periódicos, o Horse responde imediatamente com umACK(PONG). Isso impede que firewalls ou NATs encerrem a conexão por inatividade e ajuda a detectar falhas rapidamente.
2. Ciclo de Vida do gRPC no Delphi FMX: Onde inicializar?
No desenvolvimento móvel com FireMonkey (FMX), o maior pecado que um desenvolvedor pode cometer é realizar operações bloqueantes ou inicializações de rede síncronas no evento OnCreate do formulário principal.
Se você tentar abrir uma conexão TCP ou resolver DNS durante a criação do Form, o aplicativo ficará congelado na tela de Splash. Em sistemas como o Android, se a Thread principal (UI Thread) ficar travada por mais de 5 segundos, o sistema operacional exibirá a famosa mensagem de ANR (Application Not Responding) e forçará o fechamento do app.
Recomendação de Arquitetura:
- Inicialização Tardia (Lazy Loading) e Assíncrona: O canal de comunicação (gRPC Channel) deve ser inicializado fora da Thread principal (utilizando
TTask.RunouTThread.CreateAnonymousThread). - Conexão Persistente (Singleton): Criar e destruir o canal gRPC a cada requisição destrói o desempenho do aplicativo. O custo de estabelecer uma conexão HTTP/2 com handshake TLS/SSL é alto. O correto é criar uma instância persistente do canal de comunicação e reutilizá-la por todo o ciclo de vida do aplicativo.
type
TClientService = class
private
class var FInstance: TClientService;
FChannel: IGrpcChannel; // Canal compartilhado de longa duração
FUserClient: TUserServiceClient;
function GetUserClient: TUserServiceClient;
public
class function Get: TClientService;
procedure GetUserAsync(const AUserId: Integer; ACallback: TProc<TUserResponse, Exception>);
end;
procedure TClientService.GetUserAsync(const AUserId: Integer; ACallback: TProc<TUserResponse, Exception>);
begin
// Executa a chamada fora da UI Thread
TTask.Run(
procedure
var
LResponse: TUserResponse;
begin
try
LResponse := GetUserClient.GetUser(TUserRequest.Create(AUserId));
// Retorna o resultado de volta para a Main Thread para atualizar a tela
TThread.Queue(nil,
procedure
begin
ACallback(LResponse, nil);
end);
except
on E: Exception do
begin
TThread.Queue(nil,
procedure
begin
ACallback(nil, E);
end);
end;
end;
end);
end;
3. Implementando Offline First com gRPC no Delphi
O conceito de Offline First dita que a aplicação deve ser totalmente funcional mesmo sem acesso à internet. O gRPC é um protocolo de rede extremamente eficiente, mas ele não é um mecanismo de sincronização de banco de dados por si só. Para torná-lo Offline First, você deve desenhar a aplicação baseada no padrão Outbox / Sync Queue:
- Persistência Local Imediata: Quando o usuário executa uma ação (como criar um pedido), grave esses dados imediatamente em um banco local (SQLite via FireDAC, por exemplo). O usuário nunca deve esperar a resposta do servidor para continuar navegando.
- Fila de Alterações: Grave essa operação em uma tabela local de fila de sincronização (Outbox Table). Você pode guardar os dados da requisição serializados em JSON ou no próprio formato binário Protobuf.
- Monitoramento de Rede: Implemente um serviço que monitore a conectividade do dispositivo.
- Sincronização em Background: Assim que a conexão for reestabelecida, uma thread de segundo plano deve ler as transações pendentes da fila local e enviá-las via gRPC para o servidor Horse, removendo-as da fila local apenas após a confirmação de sucesso.
Por que o gRPC é perfeito para Offline First no Mobile?
O grande segredo está na eficiência. O Protocol Buffers (Protobuf) serializa os dados em binário compacto, reduzindo o tamanho das mensagens em até 70% comparado ao JSON convencional. Além disso, o multiplex do HTTP/2 permite enviar todas as requisições em lote sobre um único canal físico TCP. No ambiente mobile, menos tráfego de rede e menos conexões físicas significam menor consumo de bateria e economia de dados móveis para o cliente final.
Conclusão
O uso de gRPC com Horse no Delphi abre portas para aplicações mobile incrivelmente rápidas e responsivas. Ao centralizar a resiliência no cliente gRPC, manter o canal de comunicação ativo em um Singleton assíncrono e implementar um padrão robusto de persistência local para estratégias offline, você garante um aplicativo FMX profissional, manutenível e preparado para ambientes de produção de alta escala.
Descubra mais sobre Régys Borges da Silveira
Assine para receber nossas notícias mais recentes por e-mail.
Dê-nos sua opinião, seu comentário ajuda o site a crescer e melhorar a qualidade dos artigos.