Sharing data between `ws` implementation and `createServerFn` util
So I followed this guide https://nize.ph/blog/tanstack-start-websockets/ to implement websockets in my Start application, but I'm having some trouble being able to share data between the WS server, and some server-side routes created with
createServerFn
. My goal is to have the ability to send a websocket message from a server function. The way I've tried to do this, is to create a Map()
instance, in which I place websocket "peers", and then I'm attemting to retreive the appropriate peer from the server-side function. However, the Map isn't shared, it seems like the file where createServerFn
is located, is loaded dynamically by Start, which means the Map is always a new instance rather than being the existing one.
TL;DR on code:
- src/lib/peerManager.ts
exports a singleton export const peerManager = new PeerManager();
- src/ws.tsx
imports the singleton, handles websocket, works great
- src/lib/websocket.ts
imports the singleton but only actually imports it when receiving a request, and it's always a new instance
- src/routes/user.tsx
calls websocket.ts' function and that triggers creating a new instance without the expected peers in it.
Full code: https://stackblitz.com/edit/start-websocket-issue
Nota Bene: The peerManager was how I felt was the "only" way to share data between the websocket implementation, and the user context for a logged in user - I'm using Clerk
for auth if that matters. This maybe be an x/y problem and someone can tell me how to share a session/context between the WS and createServerFn without this peer mapping. I'm not attached to the mapping solution, it's just what I thought might work!
6 Replies
afraid-scarletOP•5mo ago
@nize I usually try to avoid pinging people directly, but since you wrote that websocket article I'm hoping maybe you might have some insight on how to make this work. I'm not expecting an answer or an immediate response, but if you have time, I would love to get your input!
correct-apricot•5mo ago
it seems like the file where createServerFn is located, is loaded dynamically by Start, which means the Map is always a new instance rather than being the existing one.not sure if this is exactly the case, it looks like Start's server fns and api routes maintain their own singleton across requests but it is indeed still separate from the websocket handler's instance. i'm not very familiar with the internals here but i assume this is because it's a separate vinxi router/entry (as we added in app.config.ts). i wonder if this is still the case with devinxi though. tanner did mention something about this in an old tweet
correct-apricot•5mo ago
afraid-scarletOP•4mo ago
Ah man that's gonna be a problem - I can't just use a database or something here, I need these events pushed as fast as I possibly can, that's why I'm doing websockets 😦
@Tanner Linsley second "sorry but not sorry" ping here - could you confirm that I'm indeed blocked on my issue here, until perhaps the devinxi-ing is completed? Basically either I use a separate backend for this, or I wait for a 2.x of tanstack start?
(ironically, two really great projects I would love to get done, and might be viable as products, use websockets, and would have the same limitation)
correct-apricot•4mo ago
Yeah, the main problem is that in the current live version, there are 2 server environments running
one for SSR and one for server functions
You'll need them to share the same space
We're SOO close on devinxi
I'd hate to see you forgo it
But I can't make a promise on when it will be ready
afraid-scarletOP•4mo ago
Thank you Tanner! I can't wait to see it!
I'm definitely not going to go somewhere else btw. I love the way TSStart handles server side events so as long as createServerFn sticks around after devinxi I'm still going to prefer this over any other solution