Ce bug m'a pris 4h à diagnostiquer
Je le documente ici pour que personne ne reperde ce temps.
Symptôme
Avec 2+ utilisateurs connectés via nodyx-relay, la sidebar membres était vide. L'online count restait à 0. Les messages Socket.IO n'arrivaient pas.
Root cause — séquentialité du relay client
Socket.IO utilise du long-polling comme transport de fallback (GET bloquant pendant 8 secondes = pingInterval).
Timeline avec 2 users et relay séquentiel :
t=0s User A : GET /socket.io/?sid=aaa → entre dans la queue
t=0s User B : GET /socket.io/?sid=bbb → attend derrière A
t=8s User A : GET se résout (réponse Socket.IO)
t=8s User B : commence à être traité
t=10s relay-server timeout → 504 Gateway Timeout
Socket.IO de User B se déconnecte → reconnect → boucle
Le fix — tokio::spawn par requête
// ❌ Avant : séquentiel — bloque tout pendant 8s
while let Some(req) = queue.recv().await {
handle(req).await;
}
// ✅ Après : concurrent — chaque requête dans son propre task
while let Some(req) = queue.recv().await {
let writer = writer.clone();
tokio::spawn(async move {
handle(req, writer).await;
});
}
L'écriture reste sérialisée via mpsc pour éviter les race conditions sur le socket TCP partagé.
Leçon
Les timeouts en cascade sont insidieux. Le symptôme (sidebar vide) était loin de la cause (séquentialité du relay). Il faut toujours vérifier la couche transport en premier.