tapir
tapir copied to clipboard
[FEATURE] Scala.js Airstream WebSocket integration
Tapir version: 1.9.0 Scala version: 3.3.1
Describe the bug
There are existing interpreters for ZIO and fs2 WebSocket support in the Fetch backend for Scala.js. When using Tapir with Laminar it would be nice to have Airstream integration. This issue is intended to generate some discussion about whether this integration is seen as something desirable and to iron out technical details.
How to reproduce?
Try using the Scala.js Fetch backend without ZIO/fs2 - WebSockets are not supported.
Additional information
I have actually made a first pass at an implementation in https://gist.github.com/vladimir-lu/bc6c7640eff5a1926a24371b099b2355 . There were some challenges, in particular:
- There is no way (that I can see) to merge(run) the incoming stream with the outgoing stream in Airstream (unlike both fs2/zio), primarily because Airstream is not meant to be a generalised effect system
- This necessitates the passing of
Ownerinto theWebSocketToPipe[_]implementation because otherwise the first half of the pipe is never started (and could be worked around e.g. by passing the input typeAas a tuple of(Owner, A)in thePipetype definition)
- This necessitates the passing of
- I am still not clear on the cancellation semantics - i.e. what to do when we want to close the websocket or when it becomes closed
- There's no equivalent of
.tailRecM/.mapAccumZIOin Airstream, which also means writing some extra code to manually fuse it to the polling loop - Monad laws? 🙄
One other observation is that I think perhaps if the web socket implementation in sttp was extendable then you could replace the JsSimpleQueue with the corresponding airstream WriteBus and basically skip past some of the almost-surely-present unlawfulness of the example implementation above.
I think I need to convince myself (probably through using the implementation a bit longer) that this is a good idea - otherwise happy to prepare a PR.
cc @raquo