9 · Acompanhando uma resolução longa¶
A maioria das verificações termina em menos de um segundo. Algumas, como uma enumeração de todas as maneiras de uma política quebrar, uma random forest grande ou uma caçada sobre um rulebook extenso, levam minutos. Enquanto um job roda, o serviço transmite o que o motor está fazendo, quadro a quadro, e este capítulo diz como lê-lo, como retomá-lo e o que fazer onde uma rede não deixa um stream passar.
O stream¶
GET /v1/solves/{id}/events
Accept: text/event-stream
Last-Event-ID: 41 (opcional; ?after=41 é o mesmo)
Authorization: Bearer qls_live_…
O stream primeiro repete tudo o que o job já registrou, depois o acompanha ao vivo, e se fecha quando o
job chega a um estado terminal. No cliente, stream=True em qualquer método de verificação lhe dá os
quadros como um iterador que termina no quadro terminal:
frames = client.verify_guardrail(
"gemini.co", "respond with permitted investment answer", "has_advising_permission",
pins={"personal_recommendation": 1}, profile="enumerate", stream=True,
)
for event in frames: # resumed by itself if the connection drops
if event.type in ("phase", "verdict", "succeeded", "failed", "stream_degraded"):
print(event.type, event.data.get("phase") or event.data.get("status") or "")
Com o curl, passe -N. Sem ele, o curl acumula a resposta e imprime a resolução inteira quando ela
termina, o que parece exatamente o endpoint não funcionando.
Os quadros¶
Todo quadro tem o mesmo envelope: id, type, job_id, seq, at e data. Só data varia, e type
é um de um conjunto fixo:
| Evento | Significado |
|---|---|
accepted |
a requisição foi validada e existe um id de job |
queued |
o job está esperando um worker; emitido de novo quando uma concessão expira, com a contagem de tentativas aumentada |
leased |
um worker o assumiu |
lease_lost |
o worker que o detinha parou de renovar a sua concessão; a tentativa é abandonada e o job volta para a fila |
started |
o solver está executando, e os argumentos com que foi executado |
compiled |
a política foi analisada e o circuito existe; as recusas de tempo de compilação já foram avaliadas a esta altura |
generation |
um passo de uma requisição de escrita assistida: o modelo consultado, a sua resposta recebida, o rascunho compilado, uma rodada concluída |
progress |
uma amostra de progresso do solver |
phase |
uma fase do solver começou ou terminou |
verdict |
a projeção do veredito, assim que o resultado é analisado e antes de os artefatos serem enviados |
artifact |
um artefato terminou de ser enviado e pode ser baixado |
succeeded |
terminal: a execução funcionou e um resultado foi analisado, seja qual for o veredito nele |
failed |
terminal: nenhum resultado foi produzido; traz o motivo classificado e o fim da saída de erro |
cancelled |
terminal: quem chamou retirou o job |
drain_requeue |
o prazo de esvaziamento de uma implantação foi excedido com o job ainda rodando; o worker deixa a sua concessão expirar de propósito, para o job voltar à fila em vez de se perder |
expired |
o job nunca foi assumido e o seu tempo de vida acabou; terminal, e nada rodou |
refused |
uma regra que a borda não conseguiu avaliar foi avaliada com a política em mãos e a requisição foi recusada; terminal, e nenhum orçamento de resolução foi gasto |
heartbeat |
o stream está vivo; nenhum estado mudou |
O quadro terminal traz o job inteiro, exatamente como GET /v1/solves/{id} o devolveria. Um cliente
que acompanhou um job até o fim não precisa de nenhuma outra requisição para saber o veredito.
O que os números de progresso dizem¶
Um quadro progress é uma amostra da fase que está rodando, e um quadro phase marca o início ou o fim
de uma fase, com o motivo que o motor dá. Quatro fases relatam progresso:
phase0, o solver SAT: quantos fatos ele já estabeleceu (unary), quantas relações de duas ou de muitas variáveis ele aprendeu (binary_xor,multi_xor) e quantas rodadas se passaram sem nenhuma.cascade, a expansão algébrica: orankalcançado e quanto ele cresceu desde a última amostra (rank_delta). Rank subindo é a expansão trabalhando; rank parado é a expansão terminada, ou presa.phase3, o fechamento que conta todas as soluções: a suaround, abasisque ele construiu e asobstructionsque restam. Enquanto ele roda, o rank fica congelado e não diz nada;basissubindo enquantoobstructionscai em direção a zero é o sinal honesto de progresso.seatbelt, a busca do reparo: quantas candidatas ela já examinou (scanned) dototal, a melhor pontuação encontrada (best) e o alvo em que ela para (target).besténullaté algo ter sido pontuado.
Uma execução curta emite quase nenhuma amostra, e as suas fronteiras de fase contam a história toda. Uma
tabela de propriedades marca cada linha com uma fronteira solve_begin que traz o id da linha, para que o
trabalho de uma linha nunca seja atribuído a outra.
Não há porcentagem¶
De propósito. O motor não consegue saber quanto tempo um fechamento vai levar até tê-lo terminado, então uma barra de progresso seria um palpite apresentado como uma medição. Os números acima são o que se sabe, e os quadros os trazem como são.
Retomando¶
id é o número de sequência do quadro, então Last-Event-ID é um cursor: devolva o último id que você
viu e receba tudo o que vem depois dele, uma vez cada. ?after=N é o mesmo cursor para uma pilha HTTP
que não define o cabeçalho. Em qualquer número de reconexões, os quadros que você recebe são exatamente a
sequência do job, uma vez cada. O cliente retoma por você.
Um worker que falha no meio de um job aparece, não é escondido: o stream traz lease_lost, depois
leased e started de novo, com attempt aumentado. O relógio do próprio motor recomeça do zero
enquanto seq continua, e todo quadro traz attempt, para que um gráfico possa manter as duas execuções
separadas.
Um comentário, : heartbeat <hora>, chega a cada 15 segundos, mais curto que o tempo ocioso de qualquer
proxy, para que um trecho silencioso de uma resolução longa não tenha a conexão cortada. Um stream em que
nada chega por vinte minutos é fechado; reconecte com o seu cursor e ele continua de onde parou.
Quando um stream não passa¶
Algumas redes acumulam ou cortam respostas de longa duração. Os mesmos quadros estão disponíveis por
consulta: GET /v1/solves/{id}/events?mode=poll&after=N devolve uma lista JSON limitada, lida do mesmo
cursor, na mesma ordem, e GET /v1/solves/{id} traz um bloco progress, o quadro mais novo por fase,
com o seq a partir do qual consultar. É a mesma informação, num ritmo mais espaçado.
O cliente passa a consultar sozinho depois de dois streams que falharam, e diz isso com um quadro
stream_degraded antes de continuar. Se um stream chega todo de uma vez, no fim, há um proxy acumulando
respostas entre você e nós; o capítulo 15 diz como encontrá-lo. O
stalwart doctor verifica se o streaming passa pela sua rede.
Os limites de streams¶
| Limite | Valor | Quando é alcançado |
|---|---|---|
| Streams por chave | o streams do seu plano |
429 stream_limit |
| Streams por job | 8 | 429 stream_limit_job |
| Novos streams por chave por minuto | 60 | 429 stream_limit_rate |
Cada um traz Retry-After. Uma chave revogada enquanto um stream está aberto é desconectada em até 15
segundos.
O que um stream não é¶
- Não é um controle. O stream só lê. Para cancelar um job,
DELETE /v1/solves/{id}. - Não é um webhook. O serviço não faz chamadas de saída para você; uma equipe que quer ser avisada constrói isso sobre este stream.
- Não é o veredito. Só o quadro terminal, ou o próprio job, traz o veredito. Um quadro de progresso que parece promissor não promete nada.
Os limites¶
- Os números de progresso descrevem o trabalho do motor, não quanto dele falta.
- Um stream que cai não perde nada se você retomar com o seu cursor; um cliente que recomeça do início recebe os quadros de novo.
- Só o quadro terminal, ou
GET /v1/solves/{id}, é a resposta.