Restricciones de campos y rangos de valores
Campos de solicitud (C→S)
| Campo | Tipo | Rango válido | Significado | Si se incumple |
|---|---|---|---|---|
op | ASCII 1B | A(0x41) · R(0x52) | Tipo de solicitud | E bad_op |
wait | u8 | 0–255 (segundos) | 0 intenta de inmediato sin cola; 1..255 limita la espera de adquisición | — (siempre válido por el tipo) |
lease | u8 | 1–250 (segundos) | Lease; 0 y 251..255 se rechazan/reservan | E bad_lease |
owner | u64 BE | todo el rango 0 – 2^64-1 | Identificador del intento de adquisición (lo genera el cliente) | — (el servidor no lo valida) |
token | u64 BE | valor emitido por el servidor | Indica qué liberar (solo R) | N si no coincide |
key | UTF-8 | 1 – 128 bytes | Nombre del bloqueo. No puede contener espacio (0x20) ni salto de línea (0x0A) | E bad_key |
- No hay wait ni lease infinitos. Los clientes oficiales redondean hacia arriba las fracciones de segundo, validan el rango y devuelven un error de entrada explícito antes de enviar, sin clamp. El lease predeterminado es de 30 segundos.
- En la API oficial,
waites el límite total del acquire desde el inicio de la llamada, pasando por local queue, reintentos de conexión definitivamente no enviados y write, hasta la respuesta. Se crea una sola monotonic operation deadline; justo antes del envío real, el writer coloca en elwaitdel frame el techo u8 de los segundos restantes. Por tanto, una conexión tardía o un failover definitivamente no enviado no puede reiniciar el server wait. Si al llegar la deadline la solicitud sigue en queue, vence como timeout definitivamente no enviado; si pudo enviarse siquiera un byte, se cierra esa session exacta y el resultado esIndeterminate. Solo unwait=0original usa wire0, y ese intento inmediato tiene otra I/O deadline finita para no esperar indefinidamente un transport bloqueado. Si unAya correlacionado justo antes de la deadline se descubre tarde en el gate de entrega del Ticket, el server waiter ya terminó: se mantiene abierta la session, se libera en compensación el exact token conocido y se devuelveIndeterminate. LosT/Bcorrelacionados siguen siendo no adquisiciones definitivas. - Para un
wait=0original, el comportamiento wire y server sigue siendo un único intento inmediato sin queue. Dentro de su transport deadline separada de cinco segundos, un fallo definitivamente no enviado puede elegir otra conexión y reintentar con el mismo owner. Una vez que pudo enviarse siquiera un byte, el acquire nunca se reenvía. - La API oficial exige
min_work_budget, que no viaja por wire. Cubretrabajo crítico + pausa prevista + finalización de commit/rollback DB, está en0..250segundos y no supera el lease normalizado. Si no, falla antes del envío con un error tipoUnsupportedDuration/InsufficientLease. - La longitud de la clave se mide en bytes, no en caracteres — los caracteres acentuados ocupan 2 bytes en UTF-8, así que una clave solo de acentuados llega a 64 caracteres.
ownersolo es un ID de correlación de respuesta, no autoridad. Reutilizarlo no devuelve un active token ni renueva el lease. Las solicitudes in-flight simultáneas de un cliente deben usar valores no nulos distintos; si el contador llega a 0 o hace wrap, los clientes oficiales fallan de forma cerrada.- Los releases explícitos y compensatorios de un token conocido tienen 5 segundos absolutos desde call/enqueue, incluidas reconexiones y reintentos.
Rconfirma éxito;Nindica que ya no existe o no es el token actual. Sin respuesta nunca se supone éxito; una cola compensatoria limitada llena recurre a la expiración del lease. bad_keycubre por igual una clave vacía, una que supere 128 bytes, una que contenga espacio o salto de línea, y UTF-8 inválido. Los clientes oficiales, además, nunca envían\r— una clave terminada en\rse convertiría silenciosamente en una clave distinta.
Campos de respuesta (S→C)
| Campo | Tipo | Rango | Aparece en |
|---|---|---|---|
token | u64 BE | 1 o más, creciendo con cada concesión | A (emisión nueva) · R/N (eco de la solicitud) |
owner | u64 BE | el valor de la solicitud sin cambios | A · T · B (eco de la solicitud) |
key | UTF-8 | el valor de la solicitud sin cambios (1–128B) | A · T · B · R · N |
addr | UTF-8 | host:port | M · L |
reason | ASCII | uno de los ocho | E |
El servidor nunca emite el token 0. Single usa un contador durante la vida del proceso; cluster usa un contador replicado por consenso y falla de forma cerrada antes del overflow. Ni wall clock ni aleatoriedad garantizan monotonía tras reiniciar.
Longitudes de cabecera fija
El tramo binario de longitud fija que sigue al op. Estos bytes pueden contener 0x0A, así que el analizador debe consumir exactamente esa cantidad antes de buscar el salto de línea.
| Dirección | op | Cabecera fija | Composición |
|---|---|---|---|
| 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 | ninguna (el texto empieza justo tras el op) |
Si faltan bytes, se devuelve E bad_request.
Tamaño de trama
| Elemento | Valor |
|---|---|
Límite de trama (sin el \n) | 192 bytes — si se supera: E line_too_long |
Solicitud A más grande | 1 + 10 + 128 + 1 = 140 B |
Solicitud R más grande | 1 + 8 + 128 + 1 = 138 B |
Respuesta A más grande | 1 + 16 + 128 + 1 = 146 B |
Trama vacía (solo \n) | keep-alive — el servidor la ignora |
El límite de 192B supera la trama máxima (146B), por lo que un cliente conforme no lo alcanza. Tras una trama estructuralmente inválida u oversized, deja de confiarse en el framing y se cierra la conexión.
Handshake de autenticación
| Elemento | Valor |
|---|---|
| Hash | SHA-256 (indicado en la línea de challenge) |
| nonce | 8 caracteres base64url |
| Digest de respuesta | 43 caracteres base64url (sin relleno) |
| Límite de línea | 256 bytes |
| Tiempo límite | 10 segundos (incluida la negociación TLS) — se cierra la conexión si se supera |
Consulta Handshake de autenticación para el procedimiento completo.
Límites del servidor
El cliente no fija directamente estos valores, pero afectan a su comportamiento.
| Elemento | Predeterminado | Ajuste | Al superar |
|---|---|---|---|
| Waiters por key | 2048 (límite 16384) | MAX_WAITERS | B (busy) |
| Waiters totales | 16384 (límite 65536) | MAX_TOTAL_WAITERS | B para ese acquire |
| Conexiones client simultáneas | 1024 (límite 8192) | MAX_CONNECTIONS | Cierre inmediato |
| Replies pendientes por conexión | 256 | constante de compilación | Cierre del cliente lento |
| Acquires in-flight globales | 4096 | constante de compilación | B para ese acquire |
| Releases in-flight globales | 512, lane separada | constante de compilación | Espera limitada hasta cerrar |
| Keys activas del cluster | 65536 | constante de compilación | B para nueva key |
El read buffer (4096B), batch de respuestas (64), progress timeout de una trama client iniciada (5 s) y sweep de expiración single (5 s) son constantes de compilación. Cluster expiry usa un deadline min-heap que valida tokens, no un escaneo completo. Véase Configuración.
La admisión de acquires, keys nuevas y waiters globales se cierra al 90 % del hard limit y solo reabre por debajo del 75 %. Por eso un acquire nuevo puede recibir B antes del límite; la capacidad reservada para release y recuperación Raft queda separada de esta histéresis.
Resumen: incumplimiento → respuesta
| Situación | Respuesta | Conexión |
|---|---|---|
| op desconocido | E bad_op | cerrada |
| Cabecera fija incompleta | E bad_request | cerrada |
lease = 0 o 251..255 | E bad_lease | cerrada |
| Clave vacía / más de 128B / con espacio o salto de línea / no UTF-8 | E bad_key | cerrada |
| Trama de más de 192B | E line_too_long | cerrada |
| Digest de autenticación no coincidente | E auth_failed | cerrada |
| Cola de espera saturada | B + owner + key | se mantiene |
| Token de liberación no coincidente | N + token + key | se mantiene |
Para todos los motivos de error y el tratamiento de la conexión, consulta Respuesta · Error E.