Actuellement en test : le code GitHub sera ouvert une fois terminé.

Contraintes de champs et plages de valeurs

Champs de requête (C→S)

ChampTypePlage valideSignificationEn cas de violation
opASCII 1BA(0x41) · R(0x52)Type de requêteE bad_op
waitu80 à 255 (secondes)0 tente immédiatement sans file ; 1..255 borne l'attente d'acquisition— (toujours valide par le type)
leaseu81 à 250 (secondes)Bail ; 0 et 251..255 sont rejetés/réservésE bad_lease
owneru64 BEtoute la plage 02^64-1Identifiant de la tentative d'acquisition (généré par le client)— (le serveur ne le valide pas)
tokenu64 BEvaleur émise par le serveurDésigne ce qu'il faut libérer (R uniquement)N en cas de non-correspondance
keyUTF-81 – 128 octetsNom du verrou. Espace (0x20) et retour à la ligne (0x0A) interditsE bad_key
  • Il n'existe aucune attente ni aucun bail infini. Les clients officiels arrondissent les fractions de seconde vers le haut, valident la plage et renvoient une erreur d'entrée explicite avant envoi, sans clamp. Le bail par défaut est de 30 secondes.
  • Dans l'API client officielle, wait est la limite globale de l'acquire, depuis l'entrée de l'appel jusqu'à la réponse, en incluant la local queue, les nouvelles tentatives dont l'absence d'envoi est certaine et le write. Un unique monotonic operation deadline est créé ; juste avant l'envoi réel, le writer place dans le wait de la frame l'arrondi supérieur u8 du temps restant. Une connexion tardive ou un failover certainement non envoyé ne peut donc pas recommencer le server wait. À la deadline, une requête encore en queue expire avec certitude sans avoir été envoyée ; si un seul byte a pu partir, la session exacte est fermée et le résultat est Indeterminate. Seul un wait=0 d'origine utilise wire 0, et cette tentative immédiate possède une deadline I/O finie distincte pour ne jamais attendre indéfiniment un transport bloqué. Si un A déjà corrélé juste avant la deadline n'est découvert qu'au gate de livraison du Ticket, le server waiter est déjà résolu : la session reste ouverte, l'exact token connu est libéré en compensation et le résultat est Indeterminate. Les T/B corrélés restent des non-acquisitions définitives.
  • Pour un wait=0 d'origine, le comportement wire et server reste une seule tentative immédiate sans queue. Dans sa deadline transport distincte de cinq secondes, une défaillance certainement non envoyée peut choisir une autre connexion et retry avec le même owner. Dès qu'un seul byte a pu être envoyé, l'acquire n'est jamais retransmis.
  • L'API officielle exige min_work_budget, absent du wire. Il couvre travail critique + pause prévue + fin du commit/rollback DB, vaut 0..250 secondes et ne dépasse pas le bail normalisé. Sinon, l'appel échoue avant envoi avec une erreur de type UnsupportedDuration/InsufficientLease.
  • La longueur de la clé se mesure en octets, pas en caractères — les caractères accentués occupent 2 octets en UTF-8, donc une clé entièrement accentuée atteint 64 caractères.
  • owner n'est qu'un identifiant de corrélation de réponse, pas une autorité. Le réutiliser ne rend pas un active token et ne renouvelle pas le bail. Les requêtes simultanées d'un client utilisent des valeurs non nulles distinctes ; si le compteur atteint 0 ou wrap, les clients officiels échouent en mode fermé.
  • Un release explicite ou compensatoire d'un token connu dispose de 5 secondes absolues depuis call/enqueue, reconnexions et tentatives incluses. R confirme le succès ; N signifie déjà absent ou token non courant. Une absence de réponse n'est jamais supposée être un succès ; une file compensatoire bornée pleine retombe sur l'expiration du bail.
  • bad_key couvre à la fois une clé vide, une clé dépassant 128 octets, une clé contenant un espace ou un retour à la ligne, et un encodage UTF-8 invalide. Les clients officiels n'envoient en plus jamais \r — une clé se terminant par \r deviendrait silencieusement une clé différente.

Champs de réponse (S→C)

ChampTypePlagePrésent dans
tokenu64 BE1 ou plus, croissant à chaque octroiA (nouvelle émission) · R/N (écho de la requête)
owneru64 BEla valeur de la requête telle quelleA · T · B (écho de la requête)
keyUTF-8la valeur de la requête telle quelle (1–128 o)A · T · B · R · N
addrUTF-8host:portM · L
reasonASCIIl'une des huitE

Le serveur n'émet jamais le token 0. Le mode single utilise un compteur limité à la durée de vie du processus ; le cluster utilise un compteur répliqué par consensus et échoue en mode fermé avant overflow. Ni l'horloge murale ni l'aléatoire ne garantissent la monotonie après redémarrage.

Longueurs d'en-tête fixe

La portion binaire de longueur fixe qui suit l'op. Ces octets peuvent contenir 0x0A : un analyseur doit donc en consommer exactement ce nombre avant de chercher le retour à la ligne.

SensopEn-tête fixeComposition
C→SA10 Bwait(1) + lease(1) + owner(8)
C→SR8 otoken(8)
S→CA16 otoken(8) + owner(8)
S→CT · B8 oowner(8)
S→CR · N8 otoken(8)
S→CM · L · E0 oaucun (le texte commence juste après l'op)

S'il manque des octets, la réponse est E bad_request.

Taille de trame

ÉlémentValeur
Limite de trame (hors \n)192 octets — au-delà : E line_too_long
Plus grande requête A1 + 10 + 128 + 1 = 140 o
Plus grande requête R1 + 8 + 128 + 1 = 138 o
Plus grande réponse A1 + 16 + 128 + 1 = 146 o
Trame vide (\n seul)keep-alive — ignorée par le serveur

La limite de 192B dépasse la plus grande trame (146B), donc un client conforme ne l'atteint pas. Après une trame structurellement invalide ou oversized, le framing n'est plus fiable et la connexion est fermée.

Handshake d'authentification

ÉlémentValeur
HachageSHA-256 (indiqué dans la ligne de challenge)
nonce8 caractères base64url
Condensat de réponse43 caractères base64url (sans padding)
Limite de ligne256 octets
Délai limite10 secondes (négociation TLS incluse) — la connexion est fermée en cas de dépassement

Voir Handshake d'authentification pour la procédure complète.

Limites côté serveur

Ces valeurs ne sont pas fixées directement par le client, mais influencent son comportement.

ÉlémentDéfautRéglageEn cas de dépassement
Waiters par clé2048 (plafond 16384)MAX_WAITERSB (busy)
Total des waiters16384 (plafond 65536)MAX_TOTAL_WAITERSB pour cet acquire
Connexions client simultanées1024 (plafond 8192)MAX_CONNECTIONSConnexion fermée immédiatement
Replies en attente par connexion256constante de compilationConnexion lente fermée
Acquires in-flight globaux4096constante de compilationB pour cet acquire
Releases in-flight globaux512, lane séparéeconstante de compilationAttente bornée jusqu'à fermeture
Clés actives du cluster65536constante de compilationB pour une nouvelle clé

Le read buffer (4096B), le batch de réponses (64), le progress timeout d'une trame client commencée (5 s) et le sweep d'expiration single (5 s) sont des constantes de compilation. Le cluster emploie un deadline min-heap validant les tokens plutôt qu'un scan complet. Voir la configuration.

L'admission des acquires, nouvelles clés et waiters globaux ferme à 90 % de chaque hard limit et ne rouvre qu'en dessous de 75 %. Un nouvel acquire peut donc recevoir B avant la limite ; la capacité réservée au release et à la récupération Raft est distincte de cette hystérésis.

Récapitulatif : violation → réponse

SituationRéponseConnexion
op inconnuE bad_opfermée
En-tête fixe incompletE bad_requestfermée
lease = 0 ou 251..255E bad_leasefermée
Clé vide / plus de 128 o / contenant espace ou retour à la ligne / non UTF-8E bad_keyfermée
Trame de plus de 192 oE line_too_longfermée
Condensat d'authentification non concordantE auth_failedfermée
File d'attente saturéeB + owner + keymaintenue
Jeton de libération non concordantN + token + keymaintenue

Pour tous les motifs d'erreur et le traitement de la connexion, voir Réponse · Erreur E.