Recipe: Broadcast to WebSocket clients
Suave does not include a built-in bus. Track sockets yourself:
open System.Collections.Concurrent
open System.Text
open System.Threading.Tasks
open Suave
open Suave.Filters
open Suave.Operators
open Suave.WebSocket
open Suave.Sockets
open Suave.Sockets.Control
let clients = ConcurrentDictionary<System.Guid, WebSocket>()
let broadcast (text : string) =
let data = ByteSegment (Encoding.UTF8.GetBytes text)
for KeyValue(_, ws) in clients do
// send returns SocketOp (ValueTask) — fire-and-forget fan-out
ws.send Text data true |> ignore
let ws (webSocket : WebSocket) (_ : HttpContext) =
let id = System.Guid.NewGuid()
clients.[id] <- webSocket
socket {
try
let mutable loop = true
while loop do
let! msg = webSocket.read()
match msg with
| (Text, data, true) ->
let s = Encoding.UTF8.GetString data.Span
// optionally call broadcast s
do! webSocket.send Text data true
| (Close, _, _) -> loop <- false
| _ -> ()
finally
clients.TryRemove(id) |> ignore
}
let app = path "/ws" >=> handShake ws
startWebServer defaultConfig appFor serialized connect/disconnect/send, prefer a MailboxProcessor.