denoland/celldPublic

self-hosted, distributed Durable Objects

Support incremental WebSocket delivery for Cloudflare Agents compatibility

DA

Celld’s [Cloudflare compatibility goal](https://github.com/denoland/celld#what-runs-on-celld) should include delivering WebSocket messages while an asynchronous webSocketMessage() handler is still running.

A concrete use case is running Cloudflare’s [AIChatAgent](https://github.com/cloudflare/agents/tree/main/packages/ai-chat). It consumes a streaming response from onChatMessage() and delivers chunks to connected clients over WebSockets. On celld, outgoing frames on hibernating WebSockets are held until the handler finishes, so users receive the response in a burst after generation completes. This prevents incremental delivery of text, tool activity, and other streamed updates through that path.

The behavior can be demonstrated without an AI provider. On a socket accepted with ctx.acceptWebSocket(), use this handler: ```js async webSocketMessage(ws) { ws.send("first"); await new Promise(resolve => setTimeout(resolve, 1000)); ws.send("second"); await new Promise(resolve => setTimeout(resolve, 1000)); ws.send("third"); } ```

Expected behavior is for the client to receive messages approximately one second apart. Celld delivers all three together after roughly two seconds. The same probe using ws.accept() and a regular message listener delivers them incrementally.

The hibernating WebSocket path currently [captures outgoing frames for the duration of the handler](https://github.com/denoland/celld/blob/v0.5.1/crates/celld/js/websocket.rs#L920). Could those frames be released as their durability requirements are satisfied, preserving send order without waiting for the entire handler to return? That would retain celld’s storage guarantees while allowing applications built with AIChatAgent to stream over WebSockets as they do on Cloudflare.

  1. bartlomiejuclosedlast month on GitHub

  2. BA

    Thanks for the report, this is now fixed and will be released in the next version.

  3. bartlomiejureferenced 81d1c52fb5belast month on GitHub

  4. bartlomiejureferenced 0aa22f091625last month on GitHub

  5. bartlomiejureferenced 46692d514ac3last month on GitHub

  6. ryreferenced def3ad02192dlast month on GitHub

  7. bartlomiejureferenced bab562b22376last month on GitHub

  8. bartlomiejureferenced af69bb4337c5last month on GitHub

  9. bartlomiejureferenced bad4649d01f0last month on GitHub

  10. dannyhagenlockerreferenced this in webSocketMessage() blocks subsequent messages on the same connection #242last month on GitHub