Restrições de Campo e Faixas de Valores
Campos de Requisição (C→S)
| Campo | Tipo | Faixa válida | Significado | Em caso de violação |
|---|---|---|---|---|
op | ASCII 1B | A(0x41) · R(0x52) | Tipo de requisição | E bad_op |
wait | u8 | 0–255 (segundos) | 0 tenta imediatamente sem fila; 1..255 limita a espera de aquisição | — (sempre válido pelo tipo) |
lease | u8 | 1–250 (segundos) | Lease; 0 e 251..255 são rejeitados/reservados | E bad_lease |
owner | u64 BE | toda a faixa 0 – 2^64-1 | Identificador da tentativa de aquisição (gerado pelo cliente) | — (o servidor não valida) |
token | u64 BE | valor emitido pelo servidor | Indica o que liberar (só R) | N se não conferir |
key | UTF-8 | 1 – 128 bytes | Nome do lock. Não pode conter espaço (0x20) nem nova linha (0x0A) | E bad_key |
- Não há wait nem lease infinitos. Os clientes oficiais arredondam frações de segundo para cima, validam o intervalo e retornam erro explícito antes de enviar, sem clamp. O lease padrão é 30 segundos.
- Na API oficial,
waité o limite total do acquire desde o início da chamada, passando por local queue, novas tentativas de conexão definitivamente não enviadas e write, até a resposta. Uma única monotonic operation deadline é criada; imediatamente antes do envio real, o writer grava nowaitdo frame o teto u8 dos segundos restantes. Assim, uma conexão tardia ou failover definitivamente não enviado não reinicia o server wait. Se a solicitação ainda estiver na queue na deadline, ela termina como timeout definitivamente não enviado; se até um byte puder ter sido enviado, fecha-se essa session exata e o resultado éIndeterminate. Somente umwait=0original usa wire0, e essa tentativa imediata tem uma I/O deadline finita separada para não aguardar indefinidamente um transport travado. Se umAjá correlacionado pouco antes da deadline só for descoberto no gate de entrega do Ticket, o server waiter já foi resolvido: a session permanece aberta, o exact token conhecido recebe release compensatório e o resultado éIndeterminate.T/Bcorrelacionados continuam sendo não aquisições definitivas. - Para um
wait=0original, o comportamento wire e server continua sendo uma única tentativa imediata sem queue. Dentro de sua transport deadline separada de cinco segundos, uma falha definitivamente não enviada pode escolher outra conexão e tentar novamente com o mesmo owner. Depois que até um byte puder ter sido enviado, o acquire nunca é retransmitido. - A API oficial exige
min_work_budget, ausente do wire. Ele cobretrabalho crítico + pausa esperada + conclusão de commit/rollback DB, fica em0..250segundos e não excede o lease normalizado. Caso contrário, falha antes do envio com erro da classeUnsupportedDuration/InsufficientLease. - O comprimento da chave é medido em bytes, não em caracteres — caracteres acentuados ocupam 2 bytes em UTF-8, então uma chave só de acentuados chega a 64 caracteres.
owneré apenas ID de correlação da resposta, não autoridade. Reutilizá-lo não retorna active token nem renova lease. Requisições in-flight simultâneas do mesmo cliente usam valores não zero distintos; se o contador atingir 0 ou fizer wrap, clientes oficiais falham de modo fechado.- Releases explícitos e compensatórios de token conhecido têm 5 segundos absolutos desde call/enqueue, incluindo reconexões e tentativas.
Rconfirma sucesso;Nsignifica já ausente ou token não atual. Sem resposta nunca presume sucesso; uma fila compensatória limitada cheia recorre à expiração do lease. bad_keycobre uma chave vazia, uma que excede 128 bytes, uma que contém espaço ou nova linha, e UTF-8 inválido, todos igualmente. Os clientes oficiais também nunca enviam\r— uma chave terminada em\rse tornaria silenciosamente uma chave diferente.
Campos de Resposta (S→C)
| Campo | Tipo | Faixa | Aparece em |
|---|---|---|---|
token | u64 BE | 1 ou mais, crescendo a cada concessão | A (nova emissão) · R/N (eco da requisição) |
owner | u64 BE | o valor da requisição sem alteração | A · T · B (eco da requisição) |
key | UTF-8 | o valor da requisição sem alteração (1–128B) | A · T · B · R · N |
addr | UTF-8 | host:port | M · L |
reason | ASCII | um dos oito | E |
O servidor nunca emite token 0. Single usa contador durante a vida do processo; cluster usa contador replicado por consenso e falha fechado antes de overflow. Wall clock ou aleatoriedade não garantem monotonicidade após reinício.
Tamanhos de Cabeçalho Fixo
O trecho binário de tamanho fixo que vem logo após o op. Esses bytes podem conter 0x0A, então o parser precisa consumir exatamente essa quantidade antes de procurar a nova linha.
| Direção | op | Cabeçalho fixo | Composição |
|---|---|---|---|
| C→S | A | 10 B | wait(1) + lease(1) + owner(8) |
| C→S | R | 8 B | token(8) |
| S→C | A | 16 B | token(8) + owner(8) |
| S→C | T · B | 8 B | owner(8) |
| S→C | R · N | 8 B | token(8) |
| S→C | M · L · E | 0 B | nenhum (o texto começa logo após o op) |
Bytes insuficientes resultam em E bad_request.
Tamanho do Quadro
| Item | Valor |
|---|---|
Limite do quadro (sem o \n) | 192 bytes — acima disso: E line_too_long |
Maior requisição A | 1 + 10 + 128 + 1 = 140 B |
Maior requisição R | 1 + 8 + 128 + 1 = 138 B |
Maior resposta A | 1 + 16 + 128 + 1 = 146 B |
Quadro vazio (apenas \n) | keep-alive — ignorado pelo servidor |
O limite de 192B supera o maior quadro (146B), então um cliente conforme não o atinge. Após quadro estruturalmente inválido ou oversized, o framing deixa de ser confiável e a conexão é fechada.
Handshake de Autenticação
| Item | Valor |
|---|---|
| Hash | SHA-256 (indicado na linha de challenge) |
| nonce | 8 caracteres base64url |
| Digest de resposta | 43 caracteres base64url (sem padding) |
| Limite da linha | 256 bytes |
| Tempo limite | 10 segundos (incluindo a negociação TLS) — a conexão é fechada se exceder |
Veja Handshake de Autenticação para o procedimento completo.
Limites do servidor
O cliente não define diretamente estes valores, mas eles afetam seu comportamento.
| Item | Padrão | Configuração | Ao exceder |
|---|---|---|---|
| Waiters por key | 2048 (limite 16384) | MAX_WAITERS | B (busy) |
| Waiters totais | 16384 (limite 65536) | MAX_TOTAL_WAITERS | B para o acquire |
| Conexões client simultâneas | 1024 (limite 8192) | MAX_CONNECTIONS | Conexão fechada imediatamente |
| Replies pendentes por conexão | 256 | constante de compilação | Conexão lenta fechada |
| Acquires in-flight globais | 4096 | constante de compilação | B para o acquire |
| Releases in-flight globais | 512, lane separada | constante de compilação | Espera limitada até fechar |
| Keys ativas no cluster | 65536 | constante de compilação | B para nova key |
Read buffer (4096B), batch de respostas (64), progress timeout de quadro client iniciado (5 s) e sweep de expiração single (5 s) são constantes de compilação. Cluster expiry usa deadline min-heap com validação de token, não scan completo. Veja Configuração.
A admissão de acquires, keys novas e waiters globais fecha em 90% do hard limit e só reabre abaixo de 75%. Assim, um acquire novo pode receber B antes do limite; a capacidade reservada para release e recuperação Raft é separada dessa histerese.
Resumo: Violação → Resposta
| Situação | Resposta | Conexão |
|---|---|---|
| op desconhecido | E bad_op | fechada |
| Cabeçalho fixo incompleto | E bad_request | fechada |
lease = 0 ou 251..255 | E bad_lease | fechada |
| Chave vazia / acima de 128B / com espaço ou nova linha / não UTF-8 | E bad_key | fechada |
| Quadro acima de 192B | E line_too_long | fechada |
| Digest de autenticação divergente | E auth_failed | fechada |
| Fila de espera saturada | B + owner + key | mantida |
| Token de liberação divergente | N + token + key | mantida |
Para todos os motivos de erro e o tratamento da conexão, veja Resposta · Erro E.