Skip to main content
Um preço que o agente vai afirmar está velho demais para afirmar. Um temporizador venceu e pede uma releitura. Um cliente observa um item e o valor dele precisa ser conferido ao vivo. Em todos esses casos, alguém precisa perguntar ao seu sistema de registro, e a Niadra nunca faz isso: ela pede, e um worker de resolução seu, rodando dentro da sua empresa com as suas credenciais, lê o objeto e devolve o que leu por POST /v1/objects/push. O mesmo código serve à releitura imediata de uma afirmação, no processo do agente, dentro de 300 ms.

Antes de começar

  • A funcionalidade state ligada no espaço e os tipos declarados com uma seção refetch: os motivos de releitura, cada um com a condição, a prioridade e o orçamento, e a unidade do orçamento (platform_call, por exemplo), nunca dinheiro.
  • Uma chave com o escopo state:push para o worker, e context para o agente que confere afirmações.

Os resolvedores

Um resolvedor é uma função sua por tipo: recebe a referência do objeto e os campos pedidos e devolve os campos lidos da fonte, com a proveniência. Registre um por tipo:
Um resolvedor pode devolver só um dicionário de campos: eles contam como observados agora, ao vivo. version é a versão do objeto na fonte, quando ela tem uma; o push só move um campo sob uma versão maior. Cada resolvedor roda na taxa que você deu e atrás de um disjuntor: 5 falhas em 30 segundos o abrem por 30 segundos, e enquanto ele está aberto nada é lido daquele tipo.

O worker

O worker toma os pedidos de releitura que a Niadra admitiu (GET /v1/state/refresh-requests), os de prioridade maior e os mais antigos primeiro, cada um emprestado a ele por 60 segundos; lê cada objeto com o resolvedor do tipo, na taxa dele; e envia o que leu por POST /v1/objects/push, com o request_id do pedido em cada item, o que encerra o pedido e a reserva paga dele. Um pedido que o resolvedor não consegue responder, o worker libera por POST /v1/state/refresh-requests/{request_id}/release: not_found quando o resolvedor devolve niadra.resolvers.NOT_FOUND (NOT_FOUND em TypeScript), porque a fonte não tem mais o objeto, e failed quando ele falhou; o pedido sai na hora e a chamada paga conta como falha. Um pedido nem respondido nem liberado é oferecido de novo, três vezes no máximo, e depois é abandonado, com a chamada paga contada como falha. Um pedido de um tipo sem resolvedor, ou cujo disjuntor está aberto, fica para o prazo dele, com um aviso no log uma vez por tipo. Resolvers.fetch() diz por que uma leitura não trouxe objeto; resolve() continua igual.
--resolvers nomeia um módulo e um export: um Resolvers já montado, ou uma função que registra os resolvedores no que ela recebe. Rode um worker por espaço, com a chave state:push dele; vários processos podem rodar em paralelo, porque cada pedido é emprestado a um só.

Quem pede, e quando

A Niadra avalia os motivos de refetch de cada tipo quando lê o objeto e quando um valor chega, e nomeia na leitura o motivo de prioridade mais alta que vale (refetch.reason), ou floor quando a observação mais nova passou da idade em que uma releitura é devida seja qual for o motivo. admitted diz se um pedido para o worker foi admitido, dentro do orçamento e nesta ordem: um motivo em never é reportado e nunca admitido; um pedido por objeto e motivo no período do orçamento (item/1h é uma hora); o min_interval do tipo entre duas releituras de um objeto; e o orçamento pago da unidade da empresa, reservado antes da leitura, em que um custo desconhecido reserva o maior medido e uma chamada paga que falha conta mesmo assim. A leitura nunca espera pela fonte e nunca falha por isso. Um exemplo de motivos, num item de loja compartilhado:
Um temporizador com refresh(<campo>) também pede releitura pelos mesmos motivos.

Revalidação de watch

Um watch avisa um cliente quando um objeto compartilhado atende a uma condição, e um aviso só vale se a condição for verdade na fonte. Quando uma escrita move o objeto e a condição passa a valer sobre um valor que não veio ao vivo da fonte (um snapshot, um cache, o que uma ferramenta mostrou), a Niadra não avisa ainda: ela abre um pedido de releitura com o motivo watch_revalidation, admitido como qualquer outro, com a prioridade e o orçamento do motivo interest_alert do tipo, um por objeto, para todos os watches dele. O worker o serve primeiro, com os outros pedidos, e o push com o request_id decide: a Niadra confere a condição sobre o objeto guardado com os valores lidos no lugar dos da fonte, mesmo quando o push foi stale_version, e envia object.watch_fired com revalidated: true só quando a condição continua valendo. Sem valor fresco, refetch.unconfirmed_watch do tipo decide: fire, o padrão, avisa com revalidated: false; drop não avisa. Isso acontece quando nenhum worker tomou pedidos nos últimos dez minutos, quando o orçamento recusou o pedido, quando o worker o liberou (not_found ou failed) ou quando ele foi abandonado depois de três empréstimos. Um tipo sem refetch, ou que lista watch_revalidation em never, não pede nada, e fire vale na hora. Quem roda o worker recebe, portanto, avisos conferidos; quem não roda recebe os mesmos avisos com revalidated: false, ou nenhum.

A releitura imediata de uma afirmação

claim_pending não vai ao worker: é admitido para a conferência no próprio processo do agente, que lê na hora. conversation.verify_claim(ref, field, value) pergunta primeiro à Niadra (POST /v1/state/verify); quando o valor não está seguro para afirmar (velho, vencido, nunca observado), lê de novo pelo resolvedor do tipo, dentro do orçamento de 300 ms, e o valor fresco decide. O valor lido entra no turno como observação, então o contrato de afirmação e a memória o veem. Um valor nunca é conferido a partir de uma cópia velha: sem resolvedor, passado o orçamento ou com o disjuntor aberto, a resposta é claim_safe: false, com a lacuna dita.
ClaimVerdict traz claim_safe, status (fresh, stale, expired, unknown), matches (se o valor dado bate com o guardado), source (niadra, resolver ou none, quando ninguém conseguiu dizer), declared_gaps, prohibitions e o value fresco que um resolvedor leu.

Conteúdo por ponteiro

Num espaço que guarda conteúdo de terceiros por ponteiro, o texto fica no seu armazenamento e a leitura traz só o marcador content (mode, sha256, pointer, scan). O resolvedor de conteúdo do SDK o recompõe dentro da sua empresa: niadra.content.register(fetch) recebe uma função que lê um ponteiro e devolve os bytes, e niadra.content.fill(context) (Python) ou niadra.content.fill(view) (TypeScript) preenche a view de estado com os textos, conferindo cada digest. O mesmo resolvedor lê os valores gravados por ponteiro num replay. Veja Só metadado.

Próximos passos

Tipos de objeto e estado

os motivos de releitura e o orçamento de cada tipo.

Afirmações

o contrato que a conferência alimenta.

Pedidos de releitura

a referência da rota que o worker consome.

Enviar estado

a referência de POST /v1/objects/push.