--- name: ws_broadcast kind: function lang: go domain: infra version: "1.0.0" purity: impure signature: "func WSBroadcast(hub *WSHub, msg []byte) error" description: "Envia bytes al canal Broadcast del hub para que se entreguen a todos los clientes WebSocket conectados. La entrega real la hace el loop Run() del hub. Bloqueante hasta que el canal Broadcast tenga espacio (capacidad 256 por defecto). Retorna error si el hub es nil." tags: [websocket, broadcast, server, fanout, infra, realtime] uses_functions: [] uses_types: [WSHub_go_infra] returns: [] returns_optional: false error_type: "error_go_core" imports: [fmt] params: - name: hub desc: "*WSHub donde estan registrados los clientes. Si es nil retorna error." - name: msg desc: "bytes a entregar a todos los clientes. Tipicamente JSON serializado de un WSMessage." output: "error si hub es nil. Nil si el mensaje se encolo en el canal Broadcast (la entrega es asincrona)." tested: true tests: ["envia mensaje al canal Broadcast del hub", "retorna error si hub es nil", "el hub entrega el mensaje a todos los clientes registrados"] test_file_path: "functions/infra/ws_test.go" file_path: "functions/infra/ws_broadcast.go" --- ## Ejemplo ```go hub := NewWSHub() go hub.Run() defer hub.Stop() // Notificar a todos los clientes conectados msg, _ := json.Marshal(WSMessage{ Type: "step_complete", Payload: []byte(`{"step":"build","status":"ok"}`), SenderID: "pipeline_runner", Ts: time.Now().UnixMilli(), }) WSBroadcast(hub, msg) ``` ## Notas Bloqueante con backpressure controlado: si el canal `Broadcast` se llena (256 mensajes pendientes), la llamada se bloquea hasta que el hub procese alguno. Esto da feedback natural al productor cuando el sistema esta saturado. La entrega a clientes individuales es no bloqueante (clientes lentos se desconectan automaticamente). Si necesitas semantica at-least-once con retry, montar la logica encima.