Resumo

  • A RFC 2188, publicada em setembro de 1997 como Informational e não como Internet Standard, definiu o ESRO para operações remotas curtas e confiáveis sobre UDP ou outro transporte não confiável e sem conexão. O documento não passou por revisão de grupo de trabalho da IETF e inclui uma advertência da IESG sobre escalabilidade.
  • O ponto mais importante para interpretar seus estados é que invoker e performer não observam um único desfecho compartilhado. Em especial, no modo acknowledged-result, um performer pode terminar com FAILURE.indication mesmo depois de o invoker ter recebido e aceitado um resultado bem-sucedido.
  • O modo de três vias compra informação adicional: RESULT.confirm ou ERROR.confirm no performer depende da chegada do ACK do invoker. O modo de duas vias, non-acknowledged-result, economiza essa mensagem e, com ela, abre mão dessa evidência derivada do par.
  • Invoke ID serve para correlação. Não autentica, não torna a operação idempotente e não prova commit durável. Da mesma forma, timeout, esgotamento de retransmissões ou uma indicação de falha local não provam, por si, que a ação de negócio não ocorreu.
  • Quando o estado fica ambíguo, a própria RFC aponta para uma operação separada de verificação. Essa escolha é particularmente importante quando repetir uma ação não idempotente pode produzir efeitos irreversíveis.

Um protocolo de operações curtas sobre uma base que não promete confiabilidade

A RFC 2188 especifica o Efficient Short Remote Operations, ESRO, como um mecanismo de baixo overhead para operações remotas confiáveis sobre UDP ou outro serviço de transporte não confiável e sem conexão. O desenho dá atenção a ambientes sem fio como CDPD, nos quais o custo de mensagens adicionais e de cabeçalhos tinha importância operacional evidente para a proposta.

O ESRO não se reduz a um par trivial de request e response. A especificação inclui segmentação e remontagem, concatenação e separação, multiplexação de aplicações e uso da porta UDP 259. Sua abstração também separa dois papéis: o invoker, que inicia a operação, e o performer, que a recebe e a executa ou rejeita.

Essa distinção de papéis é mais do que vocabulário. Ela determina quem pode observar cada fato.

A RFC também oferece dois modos para o tratamento do resultado. No acknowledged-result, o fluxo é de três vias: resultado ou erro segue do performer para o invoker, e um ACK retorna ao performer. No non-acknowledged-result, o resultado ou erro encerra o intercâmbio em duas vias, sem esse ACK final.

A diferença de uma mensagem altera a quantidade de conhecimento disponível.

O resultado pode chegar e a operação ainda “falhar” para o performer

Considere primeiro o modo acknowledged-result.

O performer recebe uma invocação, executa a operação e constrói um resultado bem-sucedido. Esse resultado é enviado. O invoker o recebe e produz a indicação correspondente. Do ponto de vista do invoker, o resultado já chegou.

O performer ainda espera outra coisa: o ACK.

Somente quando esse ACK é recebido nasce, no lado do performer, o RESULT.confirm correspondente. O mesmo raciocínio vale para ERROR.confirm quando o intercâmbio transporta um erro.

A ausência do ACK, portanto, não significa necessariamente ausência do resultado no destino. Há pelo menos histórias distintas que podem produzir incerteza no performer: o PDU de resultado ou erro pode ter sido perdido; ele pode ter chegado ao invoker enquanto o ACK foi perdido no caminho de volta; ou pode ter ocorrido uma falha local do provider.

Essas histórias não são equivalentes.

Na segunda delas, o invoker já possui um resultado bem-sucedido, embora o performer possa posteriormente esgotar suas tentativas e receber FAILURE.indication. O performer registra corretamente aquilo que sua própria máquina de protocolo conseguiu estabelecer: não obteve a confirmação que esperava. Isso não constitui prova robusta de que o invoker jamais recebeu o resultado.

É exatamente por isso que “pode ter dado certo” precisa ser entendido com rigor. A expressão significa ausência de prova protocolar decisiva no performer sobre o que ocorreu do outro lado. Não significa prova de commit da aplicação. Entre “o invoker recebeu o resultado” e “a ação de negócio tornou-se durável” ainda existe uma fronteira que o ESRO não elimina.

Falha local não é uma retrospectiva sobre toda a operação

Uma leitura apressada pode transformar FAILURE.indication em uma frase muito maior: “a operação remota falhou”.

A RFC 2188 não autoriza essa simplificação em todos os casos.

O evento de falha pertence a uma ponta e a um caminho específico da máquina de protocolo. Para interpretá-lo é necessário perguntar o que aquela ponta estava esperando, quais mensagens poderiam ter se perdido e quais eventos já poderiam ter ocorrido no outro lado.

No modo reconhecido, a perda do ACK é o exemplo decisivo. O resultado pode ter atravessado a rede e sido aceito pelo invoker. O ACK pode então desaparecer. A partir daí, o performer e o invoker carregam evidências diferentes, ambas compatíveis com o protocolo.

Há uma implicação direcional específica no sentido oposto: no modo acknowledged-result, uma falha observada pelo invoker implica falha também no performer. Essa relação definida pela especificação, porém, não transforma todas as observações em simétricas. Algumas relações são implicações particulares entre eventos particulares; elas não criam um estado universal compartilhado.

Essa diferença é essencial para sistemas de observabilidade. Se um dashboard converte todo FAILURE do performer em “ação remota não executada”, ele acrescenta uma conclusão que não veio do protocolo.

O modo de duas vias termina com menos informação

No non-acknowledged-result, o ESRO remove o terceiro passo.

O performer envia resultado ou erro, mas não espera um ACK para concluir o caminho correspondente. Por isso, RESULT.confirm e ERROR.confirm do performer nesse modo não incorporam informação nova recebida do invoker. Eles marcam um encerramento local.

O detalhe é fundamental: o nome confirm não deve ser lido fora da semântica do modo em uso.

No modo de três vias, o confirm do performer segue uma mensagem do par. No modo de duas vias, ele não prova que o invoker recebeu o resultado. A ausência do ACK reduz overhead, mas também reduz a evidência que poderia retornar ao performer.

Nesse modo, o protocolo não gera FAILURE.indication no performer como consequência normal da ausência de confirmação remota, porque não existe confirmação remota aguardada. A exceção é uma falha local do provider.

O invoker ainda pode observar falha. E essa falha, por sua vez, também não é prova de execução nem de commit da aplicação. Uma ponta pode não receber o resultado esperado sem saber, apenas a partir dessa ausência, até que ponto a operação avançou no outro lado.

O ESRO, portanto, não torna a certeza mais barata quando usa duas mensagens. Ele escolhe obter menos conhecimento.

Uma sequência de fatos, não um único bit de sucesso

A melhor maneira de ler uma operação ESRO é separar os estágios que uma interface simplificada costuma colapsar:

  1. o invoker emite uma invocação;
  2. o PDU é recebido ou perdido no caminho;
  3. o performer recebe a solicitação e executa ou rejeita a operação;
  4. o performer constrói resultado ou erro;
  5. esse resultado ou erro é enviado;
  6. ele é entregue ou perdido;
  7. o invoker produz a indication correspondente, se o protocolo chegar a esse ponto;
  8. no modo reconhecido, o ACK é enviado;
  9. o ACK chega ou se perde;
  10. o performer produz confirm ou observa uma falha local compatível com seu estado;
  11. autenticação e autorização são decididas fora daquilo que o ESRO fornece;
  12. idempotência e tratamento de duplicatas pertencem à aplicação;
  13. eventual commit durável pertence a outra camada;
  14. divergências podem exigir verificação ou reconciliação posterior.

Esses passos são relacionados, mas não intercambiáveis.

Emitir uma invocação não prova recebimento. Receber uma invocação não prova execução bem-sucedida. Construir um resultado não prova entrega. Receber um resultado no invoker não prova durabilidade de uma transação externa. Receber o ACK no performer fornece informação sobre o intercâmbio do protocolo, não sobre todas as consequências da ação.

Cada etapa deve conservar sua proveniência.

O que um ACK acrescenta — e o que ele não acrescenta

No modo acknowledged-result, o ACK tem valor porque carrega evidência de volta para o performer.

Sem ele, o performer sabe que construiu e enviou um resultado. Com ele, passa a possuir informação derivada do lado do invoker suficiente para produzir seu RESULT.confirm ou ERROR.confirm.

Essa diferença é real, mas estreita.

O ACK não autentica o invoker. Não transforma a operação em idempotente. Não garante que uma alteração foi gravada de forma durável. Não prova que um efeito externo ocorreu exatamente uma vez. Não equivale a um registro de commit de uma aplicação.

Ele prova aquilo que a máquina ESRO está definida para extrair dele.

Essa precisão ajuda a entender por que o protocolo distingue os dois modos. A terceira mensagem não é apenas overhead. Ela compra uma categoria adicional de evidência para uma das pontas.

Invoke ID resolve correlação, não identidade nem semântica

O Invoke ID é outra peça fácil de sobrecarregar conceitualmente.

Sua função é correlacionar atividade do protocolo. Isso é importante em um sistema que pode retransmitir mensagens e manter múltiplas operações, mas correlação não equivale a identidade autenticada.

A RFC 2188 não fornece autenticação. Portanto, observar um Invoke ID coerente não prova quem originou a solicitação nem se aquele ator estava autorizado a produzir o efeito solicitado.

O Invoke ID também não prova idempotência. Se duas entregas relacionadas à mesma intenção alcançam uma aplicação cujo comando produz um efeito não repetível, o simples fato de a camada de protocolo possuir um identificador de correlação não garante que o efeito seja executado uma única vez.

Tampouco prova commit.

Uma aplicação pode receber uma invocação, executar parte do trabalho, construir uma resposta e ainda possuir regras próprias para persistência, transação, autorização, confirmação externa ou reconciliação. O ESRO não absorve essas semânticas.

A mesma disciplina vale para parâmetros. A semântica de sua codificação fica fora do escopo estabelecido. Transportar ou identificar uma codificação não significa definir o significado de negócio do conteúdo.

Retransmissão cria tráfego repetido; a aplicação decide o que isso significa

A confiabilidade do ESRO envolve retransmissões. Logo, duplicatas precisam ser tratadas como possibilidade do mecanismo, não como uma anomalia cuja interpretação já vem pronta.

Uma invocação repetida pode resultar de retransmissão legítima. Isso não prova que a ação da aplicação ocorreu duas vezes.

Um resultado repetido pode ser consequência de uma tentativa adicional de entrega. Isso não prova que o performer executou duas vezes a operação.

A distinção só se resolve quando a aplicação acrescenta sua própria semântica.

Se a operação for naturalmente idempotente, repeti-la pode preservar o mesmo estado. Se não for, uma chave de negócio estável ou algum registro de deduplicação pode ser necessário para distinguir “outra entrega da mesma intenção” de “uma nova ação”.

O Invoke ID pode participar da correlação protocolar, mas não deve ser promovido automaticamente a identidade durável de negócio. Sua vida, seu reúso e suas premissas são definidos no contexto do protocolo.

Timers descrevem espera, não realidade de negócio

A RFC 2188 deixa parâmetros operacionais dependentes da rede: intervalos de retransmissão, número máximo de tentativas, inactivity time e reference-number lifetime precisam ser escolhidos para o ambiente em que o protocolo opera.

Isso significa que um timeout é inseparável de uma configuração.

Se o limite for curto diante do atraso real, a implementação pode desistir enquanto mensagens ainda estão em trânsito. Se os intervalos forem agressivos em relação à variação normal da rede, podem surgir retransmissões e duplicatas desnecessárias. Se a vida de números de referência for incompatível com atrasos e retransmissões reais, o reúso de identificadores pode complicar a interpretação de tráfego tardio.

Nenhuma dessas situações transforma o timer em um sensor de estado da aplicação.

Timeout significa que o evento esperado não foi observado dentro do intervalo estabelecido. Não significa automaticamente que a invocação não chegou, que o performer não executou, que o resultado não foi produzido, que o resultado não chegou ao invoker ou que nenhum estado durável foi criado.

Tratar o timer como oráculo exige informação que ele não possui.

A operação de verificação reconhece formalmente a ambiguidade

A sugestão de uma operação separada de verificação é um dos aspectos mais instrutivos da RFC 2188.

Quando um performer chega a uma falha ambígua depois de ter enviado resultado ou erro, uma alternativa ao retry cego é perguntar pelo estado.

A diferença entre as duas estratégias é profunda.

O retry pressupõe que repetir a ação seja aceitável diante da incerteza. A verificação transforma a incerteza em objeto explícito do protocolo da aplicação: em vez de inferir que a operação não ocorreu, procura descobrir qual estado existe agora.

Isso é especialmente importante para operações não idempotentes.

Imagine uma ação cujo efeito não possa simplesmente ser repetido. O performer executa a ação, envia sucesso, o invoker recebe esse sucesso e o ACK se perde. O performer posteriormente observa falha. Se essa falha for convertida diretamente em nova execução da ação de negócio, a aplicação estará tratando “não sei se o outro lado recebeu a confirmação” como se significasse “a ação anterior certamente não aconteceu”.

Nada na RFC sustenta essa equivalência.

Uma operação de verificação não elimina toda incerteza de sistemas distribuídos. Ela própria pode sofrer perda ou falha. Seu mérito é outro: cria uma forma explícita de perguntar sobre o estado relevante em vez de inventá-lo a partir da ausência de uma mensagem.

Autenticação e autorização pertencem a outra fronteira

O ESRO não fornece autenticação.

Isso precisa permanecer visível em qualquer interpretação operacional. Correlação de mensagens, integridade da máquina de estado e chegada de um resultado não devem ser promovidas a evidência de identidade autenticada.

Da mesma maneira, uma rejeição por autenticação ou autorização externa não deve ser misturada com perda de rede.

Uma solicitação pode chegar corretamente ao performer e ainda ser rejeitada por uma política externa ao ESRO. Retransmitir a mesma mensagem não corrige credenciais inválidas nem concede permissão.

O inverso também é verdadeiro: a ausência de uma resposta não permite concluir que houve rejeição de autorização. A mensagem pode ter sido perdida antes de qualquer decisão desse tipo.

Proveniência importa porque as ações corretivas são diferentes. Perda pode justificar retransmissão protocolar. Rejeição de autenticação exige correção da identidade ou da política. Ambiguidade após execução pode exigir verificação. Commit inconsistente pode exigir reconciliação.

Commit durável tem um relógio diferente

Uma operação pode estar concluída para o protocolo e ainda não estar concluída para o negócio.

A RFC 2188 não define commit durável de estado de aplicação. Portanto, mesmo um intercâmbio protocolar completamente bem-sucedido precisa ser interpretado dentro desse limite.

Pode haver um instante em que o performer executou a ação, outro em que construiu o resultado, outro em que o invoker recebeu esse resultado, outro em que o ACK retornou e outro em que um sistema externo tornou o efeito durável.

Esses instantes podem coincidir em uma implementação simples. O protocolo não permite presumir que sempre coincidam.

Também é possível que o estado de negócio já esteja consolidado enquanto alguma ponta ainda carece da evidência protocolar que desejava. O caso de ACK perdido no modo reconhecido ilustra a forma geral do problema: a falta de confirmação em uma camada não desfaz automaticamente fatos já ocorridos em outra.

Por isso, “sucesso do ESRO” e “commit durável” devem ser registrados separadamente quando ambos importam.

O contexto histórico deve permanecer proporcional à evidência

A RFC 2188 apareceu em setembro de 1997 como Informational. Não é um Internet Standard. Seu material de status registra a ausência de revisão por grupo de trabalho da IETF e a advertência da IESG sobre escalabilidade.

Esses fatos delimitam o documento historicamente.

Eles não diminuem a utilidade de suas semânticas, mas impedem que a especificação seja apresentada como consenso universal sobre operações remotas na Internet.

A RFC 2524 mostra um uso pretendido de ESRO para submissão e entrega eficiente de e-mail. Isso é evidência de aplicação arquitetural do mecanismo. Não é evidência suficiente para afirmar prevalência atual, adoção comercial ampla, desempenho superior ou sucesso universal de implementações.

A RFC 1831, por sua vez, oferece um contraste adjacente dentro da história de mecanismos de chamada remota. Ela não transforma a RFC 2188 em resumo da história geral de RPC. ESRO possui papéis, primitives, modos de confirmação e semânticas de falha próprios, e é nesses detalhes que a análise precisa permanecer.

A lição central é uma disciplina de evidência

O aspecto mais durável da RFC 2188 não depende de tratar ESRO como modelo universal. É o rigor com que o protocolo obriga o leitor a perguntar quem sabe o quê.

O invoker sabe que emitiu uma operação antes de saber se ela chegou.

O performer pode saber que recebeu uma solicitação sem que o invoker saiba que ela foi recebida.

O performer pode executar e construir um resultado.

O invoker pode receber esse resultado.

O performer pode ainda não saber que o invoker o recebeu.

Um ACK pode acrescentar essa evidência ao performer.

A perda desse ACK pode deixar o performer em falha mesmo quando o invoker já registrou sucesso.

E nenhuma dessas observações, isoladamente, prova autenticação, idempotência, autorização, commit durável ou reconciliação final.

Essa não é uma fraqueza retórica da especificação. É o mapa real de suas fronteiras.