-
Notifications
You must be signed in to change notification settings - Fork 163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cloudflare Worker Compatibility/Integration #608
Comments
It might be relevant that CF Workers has a tcp sockets connect() api. They use it for creating database connectors and much more. Here's a relevant blog article as well https://blog.cloudflare.com/workers-tcp-socket-api-connect-databases/ which seems to address all of these issues (dns, tls etc..). Perhaps that API could be used to make this a simpler process for you? It might not need any "development" beyond just providing a snippet (or small library, e.g. They also seem to be open to collaborating with seemingly competing products, such as Upstash, Turso and more, so would surely help you as well. Finally, they're also proposing this api as a general standard https://github.com/wintercg/proposal-sockets-api |
Their even newer Hyperdrive service seems like it might be great fit for all of this as well. It does two main things:
I'm sure that this wouldn't be useful for every NATS implementation, but surely could be useful for things like KV operations? Blog announcement: https://blog.cloudflare.com/hyperdrive-making-regional-databases-feel-distributed/ |
I fiddled around for a while and finally got this to work after learning about telnet. Importing I ran a NATS docker server on a remote server, and connected to it in one local terminal with Then using cloudflare wrangler on my local machine I ran and triggered the worker via the browser. The worker connects to the remote nats server and sends the PUB message. The subscriber on the local machine using nats-cli then receives the message successfully. Obviously telnet is a disaster, so it would be great if cloudflare:sockets connect() could be integrated into nats.js, perhaps with some sort of option/flag to choose it vs the standard mechanisms. Surely not a big job! Some docs that I found helpful: Also, once this has been integrated, it seems to me that adding a quick doc (and perhaps even blog post or video) on this would be useful as well! Likewise letting CF know about it so that they can it to their integration docs, which would bring more attention to NATS. I created a thread in their Discord server about this - hopefully someone will reply.
|
Just for capturing:
|
It's a severely limited node environment. |
CF workers has compatibility for most of those modules, as described in this link. https://developers.cloudflare.com/workers/runtime-apis/nodejs/ If you add And, as described above, using the connect() function from cloudflare workers TCP socket mechanism rather than nats.js' connect() allowed me to successfully connect to NATS and send a telnet PUB message that was received by a subscriber via nats-cli. So, I'm hopeful that you could add an option that allows us to bypass nats.js' connect() in favour of Cloudflare's Though I guess we would still have issues deploying the script due to missing (perhaps unused) node dependencies in cloudflare - perhaps a lightweight nats-cf.js fork could work? Whatever the case, I don't think that much needs to be done to allow for cloudflare compatibility! I'd be happy to help test etc |
That would require a whole new client transport - effectively requiring yet another javascript client. With that said using the nats.ws - which is an ES compliant library, I was able to get it running with a single change in the library using denoflare. How to do it with wrangler is another exercise. import { NatsConnection, connect } from '/Users/aricart/Dropbox/code/src/github.com/nats-io/nats.ws/src/mod.ts';
let nc : NatsConnection;
export default {
async fetch(request: Request, env: any) {
if(!nc || nc.isClosed()) {
nc = await connect({ servers: ['wss://demo.nats.io:8443'] });
}
try {
return new Response('connected to ' + nc.getServer());
} catch (e) {
return new Response(e.message)
}
},
} |
Thank you! I just confirmed that using Either way, the following error is then shown
If you modify fillRandom to the following, this error no longer happens - the issue being that crypto.getRandomValues() seems to not be available in node (I found many reports of this)
But then another error pops up. I assume that'll keep happening and have no idea how deep it'll go. So, yeah, it seems like unless you folks really want to roll up your sleeves (or get collaboration from Cloudflare's team), this might not be worth your effort (unless you find it to be a strategically important priority!) I will give the nats.ws library a try and report back - I'm averse to using websockets in the browser for various reasons, but I don't have any particular objection to using them in Cloudflare Workers. Thanks again for your attention and help! |
I get this error with the nats.ws code you provided.
If I add
If I ignore NatsConnection altogether and use this code,
then i get this error sporadically:
other times I get this in the browser If I use step debugging, the issue seems to come from these lines
Ultimately, I just don't think I can get this to work. I'm a php developer so this is all beyond my capabilities/knowledge. But if someone more competent is willing to roll up their sleeves (or guide me, but then they might as well just do it themselves...), then I really do think it should be possible to get it working for Cloudflare Workers! |
Thank you for your efforts @nickchomey , the JS world can be an endless rabbithole of stuff like that... I believe this would be a really good thing to get working and the reason why it hasn't happened yet might be because the JavaScript community tends to prefer cloud services instead of self-hosting things, and NATS unfortunately doesn't have something like upstash redis (afaik) ; an HTTP client for Redis which makes it much easier to use Redis with non node.js environments. Unfortunately the HTTP client doesn't work with redis pub/sub, hence how I found-out about this thread. I would love to have an official way to use NATS with cloudflare workers and will subscribe to this issue. |
@Hebilicious the conversation continued somewhere in slack - I think the link is in this issue somewhere. We ultimately concluded that this would be very difficult to implement, and surely not any time soon. For my own purposes, I will either use nats.ws straight from the browser or, more likely, add an SSE mechanism to this existing nats-caddy-bridge module for caddy. This will allow various benefits
Anyway, I hope this helps! |
great to see this. I too am interested in running workers on Cloudflare with a connection to NATS. I concluded that CF workers is too restricted and so then went in the direction of exposing NATS over HTTP and SSE and HTTP3 Web Transports. SO here's some links relating to all this that I hope is useful. https://github.com/yomorun/yomo/tree/master/example/2-iopipe is a good example because NATS and Pipes relate to each other in terms of data flow patterns. Yomo uses http3 and thats why it's fast and has geo load balancing. Can we run Yomo as a CF Worker was then where I wanted to head. https://github.com/syumai/workers allows running golang works on CF workers. https://github.com/tractordev/wanix allows running your worker in a browser also over http3 etc. https://github.com/Gianfranco753/caddy-nats-bridge allows running your worker on a sever SO you can see where I am going with this... NATS over HTTP3, so that we can run workers on CF, Browsers, servers. The synergy is rather obvious in the feature section: https://github.com/syumai/workers?tab=readme-ov-file#features. OMG that looks a lot like NATS endpoints :) |
@gedw99 im having trouble making sense of all of this. It seems like it all spans numerous issues - running nats client in cloudflare worker (this issue), caddy nats bridge module (the issue you opened in another repo that I linked to), another fork of the caddy nats bridge, wasm, and more. I'm sure there's a lot of great ideas here, so it would be helpful if you could both organize them a bit more, suggest what goes where, and, most of all, let us know what you've successfully implemented. As I mentioned in my previous comment, I'm now most interested in running a Caddy nats sse server/bridge, which (I think) would obviate the need for any of this fancy stuff with CF workers - just create an sse connection between the browser and caddy, which could be proxied through CF workers' native http support. If that's something that you've already had some success with, or would like to help me build, perhaps we can move the conversation over to the caddy nats bridge issue you created and I linked to? |
Hey @nickchomey Yeah I can see how it might be confusing and yes I am happy to discuss over at sandstorm/caddy-nats-bridge#3 Hopefully this helps explains the gist of why I had those 3 links. Forgive me for presuming and of course you and I probably have slightly differing agendas / intentions. It shows how to run a NATS bridge over HTTP 1, 2, 3 / SSE and / or HTTP 3 Web Transport. HTTP 3 Web Transport is preferred for UDP perf reasons, but we need SSE too because of Apple keeping HTTP3 Web Transport behind feature flags ( for now ). If you study Yomo you can see that they also have fallbacks and have presence and a few other important things. Then once you have that you have a NATS bridge like above you then have 3 places to run your workers via the code I linked to:
Those 3 places are really 3 layers of caching. We know that NATS and CQRS are synergistic patterns. So events flow from the centre ( your server ) producing material data views using WASM workers. On top of that though, you can decide where you want those wasm workers to live and so hence where you want the Materialised data views to live. So really all I am suggesting is that Caddy NATS bridge needs to incorporate HTTP 1, 2, 3, and http3 web transport. HTTP / SSE is definitely also needed, and then later HTTP3 Web Transport makes sense too. |
Most of all, I'm just not sure how any of this relates to running a NATS client in a Cloudflare Worker, which is what this issue is about. Are you perhaps mistaken that this is the nats.js repo rather than the caddy nats bridge repo? The only part that seems relevant is the prospect of running nats in a CF worker via wasm. Though I wonder if that's at all possible given that the CF worker runtime doesn't have the requisite node APIs. Have you tried this at all? Anyway, I'm quite keen to work on caddy nats bridge. I should be able to start this week and am eager to learn more about all of this stuff and perhaps implement it there. Why don't we carry on over there? |
@nickchomey sure we can touch base over there. |
I use nats.go here for CF
yes https://github.com/syumai/workers with nats.go works as wasm. its def a nice way to write workers. |
@gedw99 please share some details on how to implement this! |
I don’t have it working but the skeleton code is there to be able to adapt nats.go into it because nats.go also compiles to WASM using tinygo. I know this because I have used nats.go that way. https://github.com/syumai/workers/tree/main/_examples/sockets Looks like a decent path finder to work with nats. |
Cloudflare workers have added a considerable amount of support for Node APIs. I havent tried NATS on it yet, but I bet it will work now. Announcement |
If the test and bench mark code is in a repo , it would be easier . I am using golang and nats.go . So can also put that in the same repo . |
It's not clear what you mean by this As for golang, the point here is that natsjs should work, and be smaller, faster, cheaper and much more integrated with cf workers' APIs than golang/wasm. That's a conversation for a different place |
@nickchomey even better, Deno on the current release is supporting node transport - I am considering getting rid of the custom Deno transport and just using the node transport, this will eliminate something else to maintain. The new nats.js repo, (https://gitHub.com/nats-io/nats.js) streamlines deps depending on the modules used, so I think all of this will come together nicely soon |
Great! I wonder if this and other issues should be moved to the new natsjs repo? |
not yet - very soon now. |
Proposed change
It currently isnt possible to use nats.js in Cloudflare workers due to some missing nodejs modules. Specifically
fs
anddns
(at least from what I found - there could be more)It appears that
fs
is only used if you specify TLS certs in the connection. But it doesn't appear to be possible to bypassdns
.In a conversation in Slack, a team member said that an option could be added to bypass dns resolution.
Additionally, he said that changes to/related to
nuid.ts
might be needed.Use case
It would be great to be able to use NATS with Cloudflare Workers, so that connections could be made to NATS servers from the largest edge network.
One use case (among surely infinite) would be to use your NATS Jetstream KV instead of Cloudflare Workers KV, which has up to a 60 second propagation delay for KV writes while NATS KV is "immediately consistent".
I could also see use cases such as wanting to create a NATS connection from CF Workers, rather than directly from a browser client.
In fact, it would be SUPER cool if we could connect from, say, a browser to a CF Worker, which then opens and maintains a connection to a NATS server and subscribes to subjects/streams or watches KV changes. Then any changes could be returned to the browser via, say, an SSE keepalive connection. This would avoid the browser having to do anything with NATS, and could also make use of the CF worker to do any heavy processing prior and just returning, say, HTML to the browser.
It is perhaps possible that
nats.ws
could already be used with CF workers, but surely it makes most sense to use the native protocol.More generally, Cloudflare's mission (I've seen it stated somewhere) seems to be to be a sort of operating system for the global internet. An integration with NATS, which makes it so simple to integrate different backend services, seems like a natural fit. Cloudflare could be the front-end/gateway to connect to a NATS-based backend infrastructure.
Contribution
I doubt I could provide much code, but would be happy to help test it if needed.
The text was updated successfully, but these errors were encountered: