nats-io / nats.go

Golang client for NATS, the cloud native messaging system.
https://nats.io
Apache License 2.0
5.3k stars 671 forks source link

Support for wasm #661

Open trojek opened 3 years ago

trojek commented 3 years ago

Feature Request

Support for WebAssembly

Use Case:

Use NATS from browser without using JS binding.

Proposed Change:

Add support for wasm.

Who Benefits From The Change(s)?

People who want to use NATS in WebAssembly.

Alternative Approaches

Use JS binding.

cameronbraid commented 2 years ago

Another important use case is to write a Envoy Proxy Filter https://istio.io/latest/docs/concepts/wasm/

john-livelyvideo commented 2 years ago

any headway on this front?

derekcollison commented 2 years ago

We have looked a bit at getting a port running under TinyGo. What specific use case are you looking for in the browser? I believe you can compile to wasm now and the Go client has websocket support, so wanted to make sure I understood the ask.

john-livelyvideo commented 2 years ago

@derekcollison I'm simply trying to figure out if it's possible to run golang/webassembly in the web browser, while using the go websocket client.

derekcollison commented 2 years ago

Not sure if that would be a good experience over the TS/JS client or not. I think you would need to bridge to JS for access to the websocket IIRC.

john-livelyvideo commented 2 years ago

All we need is a generic interface for sending/recv'ing websocket frames which works both natively and in the browser, right?

https://natsio.slack.com/archives/CM3T6T7JQ/p1652115060809699?thread_ts=1652109614.003509&cid=CM3T6T7JQ

gedw99 commented 2 years ago

@derekcollison

i also wanted to use the nats golang client from wasm to use in a browser. I really prefer to not have to mess with TS / JS client.

Can you explain why the experience would be bad ? The golang client tries to do its own client side load balancing if its talking to a NATS Cluster , which is pretty cool. No need for cloud load balancers.

john-livelyvideo commented 2 years ago

there are a slew of other languages which compile to wasm in the browser (ie c#, rust, assemblyscript, c++, etc.), using golang would be my preferred way of bridging over to them via a homegrown local event bus which runs in the browser.

derekcollison commented 2 years ago

@gedw99 the TS/JS clients can do the same. I believe you would need to jump through to JS to access the websocket from the TS/JS client regardless. But I could be wrong.

john-livelyvideo commented 2 years ago

@derekcollison that is correct, but that's a pretty simple interop between golang/js, right? per the framing i mentioned earlier?

john-livelyvideo commented 2 years ago

see the webassembly example in pion as a reference https://github.com/pion/webrtc/blob/8c31eb98dd78c813d09deb249bdc977b83bff3f0/examples/README.md#webassembly

derekcollison commented 2 years ago

Will take a look, thanks.

gedw99 commented 2 years ago

Hey all,

I am using the NATS Rountripper for third parties to be able to call into my NATS "system". It works great with Connect. That's one use case sorted. This however only supports HTTP RPC. So its pull based.

But i need my own GUI clients a way to talk to NATS and to have 2 way communications. I use GIOUI to build clients. Love it and makes it easy and fast to build Golang GUI. NATS.go works great from Desktop and Web over tcp. NATS.go does NOT work from WASM Brower :) Hence why i am explaining this use case and ways we can build a test harness if we want.

Here is a nice and simple REST example written in Golang and using the GIOUI gui libs. https://github.com/bpingris/gioui-requests. You can compile this to Web ( WASM), Desktop, Mobile, Apple TV ) currently. I plan to extend it to be a good Test harness for NATS Websockets and NATS TCP as well as NATS HttpRoundtriper.

If we compile to tinygo, I would be running WASM nats.go at the Service Worker layer. Service workers have access to networking and indexeddb. They also run in the background, even when the Browser "tab" is closed, if the user installs as PWA. Recently IOS safari even supports it ( shock horror ).

here is the Chromium Test for it: https://chromium.googlesource.com/external/w3c/web-platform-tests/+/master/service-workers/service-worker/websocket-in-service-worker.https.html

Here is the Safari IOS PWA capabilities summary. Web SOckets and streams are there: https://firt.dev/notes/pwa-ios/

derekcollison commented 2 years ago

I am supportive of getting the client to compile under TinyGO, or have another client targeting it. I believe the only thing is the encoded connections and GOB IIRC.

caspervonb commented 1 year ago

Unfortunately this might not be feasible at this time due to upstream blockers.

It seems that TinyGo doesn't support some of the prerequisite runtime functionality needed, such as timers (https://github.com/tinygo-org/tinygo/issues/1037) so ultimately I don't think it's feasible to implement this without having a specialized implementation that avoids the use of those runtime calls completely.

gedw99 commented 1 year ago

Tinygo is rapidly catching up to the standard golang wasm compiler though.

For now we could compile with the standard golang wasm compiler , which would mean it’s a larger file. Later change o we to Tinygo as and when feasible.

For wasm websockets there are many example of golang code that uses websockets and runs as wasm in the browser.

Fetch with wasm to avoid net/http golang lib import shows this concept: https://github.com/marwan-at-work/wasm-fetch

the js calls are wrapped here: https://github.com/marwan-at-work/wasm-fetch/blob/master/fetch.go

the same thing should work for web socket / https3 WebTransport. Yes I know nats server does not yet support http3 WebTransport yet.

https://pkg.go.dev/nhooyr.io/websocket?utm_source=godoc Support wasm websockets. I have used it many times.

so I don’t really see any technical blockers for making this happen.

nats server has wasm build tags, and we would just need to do the same for NATS.go

Here is a link to a complete golang client and server using the above approach that does pub sub . The golang client compiles to wasm as well as non wasm .

https://git.sr.ht/~whereswaldon/pointstar

derekcollison commented 1 year ago

There will be a TinyGo client in the future.

gedw99 commented 1 year ago

https://github.com/oderwat/go-nats-app works now.

uses https://github.com/nhooyr/websocket