💻 Développement

dev-websocket-designer

Conception de systèmes temps réel avec WebSocket — SignalR, Socket.io, scaling horizontal et stratégies de reconnexion.

⚡ Installation & lancement en 1 commande

Copiez-collez dans votre terminal : le skill s'installe dans ~/.claude/skills et Claude Code se lance directement dessus.

macOS / Linux
curl -fsSL https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.sh | sh -s -- dev-websocket-designer --launch
Windows (PowerShell)
iex "& { $(iwr -useb https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.ps1) } dev-websocket-designer -Launch"

🚀 Déjà installé ?

claude "/dev-websocket-designer"

Ou tapez /dev-websocket-designer dans une session Claude Code, ou décrivez simplement votre besoin — le skill se déclenche automatiquement via le skill-router.

🔑 Déclencheurs automatiques

Le skill s'active automatiquement quand votre demande contient :

WebSockettemps réelSignalRSocket.ioreal-timepush notifications

📦 Installation manuelle

git clone https://github.com/khalilbenaz/claude-skills-collection.git cp -r claude-skills-collection/skills/dev-websocket-designer ~/.claude/skills/

Payload du plugin : skills/dev-websocket-designer · source éditable : dev-skills/websocket-designer

📖 Manuel

WebSocket Designer

1. Choisir le bon protocole temps réel

BesoinSolution recommandéeRaison
Bidirectionnel, faible latenceWebSocket natif / SignalR / Socket.ioFull-duplex sur une seule connexion TCP
Serveur → client uniquementSSE (Server-Sent Events)Plus simple, traversée proxy meilleure
Polling toléré, contraintes infraLong pollingFonctionne partout sans port spécial
< 1 000 connexions simultanéesWebSocket natifPas besoin de lib externe
Stack .NETSignalRNégociation automatique + fallback intégré
Stack Node.jsSocket.ioRooms, namespaces, reconnexion built-in

Règle décisive : si un proxy ou load balancer ne supporte pas l'upgrade HTTP→WS, préfère SSE ou assure-toi que le backplane est configuré avant de commencer.


2. Concevoir le protocole de messages

Définis un contrat JSON structuré avant d'écrire une ligne de code.

// Enveloppe standard
{
  "type": "CHAT_MESSAGE",       // action discriminante
  "channel": "room:42",         // scope / destinataire
  "payload": { "text": "..." }, // données métier
  "correlationId": "uuid-v4",   // pour ack / replay
  "ts": 1719230400000           // timestamp epoch ms
}

Types d'événements minimum à définir :


3. Implémenter le serveur

SignalR (.NET 8)

// Program.cs
builder.Services.AddSignalR(o => {
    o.MaximumReceiveMessageSize = 32 * 1024; // 32 KB max
    o.EnableDetailedErrors = app.Environment.IsDevelopment();
});
app.MapHub<ChatHub>("/hubs/chat");

// ChatHub.cs
[Authorize]
public class ChatHub : Hub
{
    public async Task SendMessage(string channel, string text)
    {
        // Vérifier l'autorisation sur le canal
        if (!await _authService.CanWriteAsync(Context.UserIdentifier, channel))
            throw new HubException("Forbidden");

        await Clients.Group(channel).SendAsync("ReceiveMessage", new {
            From = Context.UserIdentifier,
            Text = text,
            Ts = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
        });
    }

    public override async Task OnConnectedAsync()
    {
        // Rejoindre les canaux de l'utilisateur dès la connexion
        var channels = await _channelService.GetUserChannelsAsync(Context.UserIdentifier);
        foreach (var ch in channels)
            await Groups.AddToGroupAsync(Context.ConnectionId, ch);

        await base.OnConnectedAsync();
    }
}

Socket.io (Node.js / TypeScript)

import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";

const io = new Server(httpServer, {
  cors: { origin: process.env.ALLOWED_ORIGIN },
  maxHttpBufferSize: 32 * 1024, // 32 KB
  pingTimeout: 20_000,
  pingInterval: 10_000,
});

io.use(async (socket, next) => {
  const token = socket.handshake.auth.token;
  const user = await verifyJwt(token); // lance une erreur si invalide
  socket.data.user = user;
  next();
});

io.on("connection", async (socket) => {
  const { userId } = socket.data.user;
  const channels = await getChannels(userId);
  socket.join(channels);

  socket.on("CHAT_MESSAGE", async ({ channel, text }) => {
    if (!channels.includes(channel)) return socket.emit("ERROR", { code: 403 });
    io.to(channel).emit("CHAT_MESSAGE", { from: userId, text, ts: Date.now() });
  });
});

4. Implémenter le client avec reconnexion robuste

// Reconnexion avec exponential backoff + jitter (vanilla WS)
function createWebSocketClient(url: string) {
  let ws: WebSocket;
  let attempt = 0;
  const MAX_DELAY = 30_000;

  function connect() {
    ws = new WebSocket(url);

    ws.onopen = () => {
      attempt = 0;
      // Rejouer les messages en attente
      drainQueue();
    };

    ws.onmessage = (e) => handleMessage(JSON.parse(e.data));

    ws.onclose = (e) => {
      if (e.code === 1000) return; // fermeture propre
      const delay = Math.min(1_000 * 2 ** attempt + Math.random() * 500, MAX_DELAY);
      attempt++;
      setTimeout(connect, delay);
    };
  }

  connect();
  return { send: (msg: object) => ws.send(JSON.stringify(msg)) };
}

SignalR client : utilise withAutomaticReconnect([0, 2000, 5000, 10000, 30000]) — les intervalles sont en ms.


5. Scaler horizontalement

Redis backplane SignalR

builder.Services.AddSignalR()
    .AddStackExchangeRedis("redis:6379,abortConnect=false", o => {
        o.Configuration.ChannelPrefix = RedisChannel.Literal("myapp");
    });

Redis adapter Socket.io

import { createClient } from "redis";
import { createAdapter } from "@socket.io/redis-adapter";

const pub = createClient({ url: "redis://redis:6379" });
const sub = pub.duplicate();
await Promise.all([pub.connect(), sub.connect()]);
io.adapter(createAdapter(pub, sub));

Points clés :


6. Sécurité


7. Monitoring

Métriques essentielles à exposer (Prometheus / OpenTelemetry) :

MétriqueSeuil d'alerte typique
ws_connections_active> 80 % de la capacité max
ws_messages_per_secondpic anormal × 3
ws_reconnect_rate> 5 % des clients/min
ws_message_latency_p99> 500 ms
ws_errors_totaltoute augmentation soudaine

Anti-patterns et pièges