Skip to content
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

Bug: reconnect closed/bad WS connection #78

Open
tcardlab opened this issue Aug 16, 2024 · 1 comment
Open

Bug: reconnect closed/bad WS connection #78

tcardlab opened this issue Aug 16, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@tcardlab
Copy link
Contributor

tcardlab commented Aug 16, 2024

I know there has been and will continue to be a lot of changes to the WS implementation in TS SDK, so this might be out dated:

  • If you use a bad token to create a client and attempt connection, WS token fetch errors, yet onConnect is still still triggered.
    • This then allows subscribe to error.
  • Despite WS failing to connect or even closing, client.live remains true.
  • I cannot trivially reconnect once WS has closed (afaik). I have to reload the whole page and start over after deleting the key.

This has been the case with 0.8 and 0.10, i have not test 0.11 yet.

Perhaps something is wrong with my implementation? Or am i misunderstanding something?

A the moment, my workarounds are just reload the page as mentioned or validate the token b4 attempting to connect.

@PuruVJ PuruVJ added the bug Something isn't working label Aug 19, 2024
@tcardlab
Copy link
Contributor Author

tcardlab commented Aug 26, 2024

Created a min-reproduction for v0.10.0 and v0.11.0 just to clarify whats going on. You can find the relevant connection code under site/variants/*. I'll provide some images and code here in hope of saving you the trouble of running it.

TLDR:

  • Bad token should either generate a new one automatically (similar to an undefined token).
    • I believe this is happening behind the scenes (as we get a proper identity), but the client token value is not updated appropriately nor passed to .onConnect().
  • Otherwise there should be a defined way to determine when a bad token was submitted and how to proceed from there.
  • Errors relevant to the connection process are hard to catch.
  • A new connection cannot be established after closing (might be bad for places with spotty internet).
    • This is because .disconnect() does not update client.live which then prevents .connect() from running again.

Routes:

/pages/works

This page uses an undefined token to guarantee a valid token gets generated and demonstrate a properly functioning page (nothing too interesting).
Screen Shot 2024-08-25 at 12 19 25 AM

/pages/uncaught

This page demonstrates what a connection with an invalid token looks like.
Both connect().catch() and client.onError() miss the error.
We connect with a new token, but neither the onConnect callback token nor client.token are updated.
Screen Shot 2024-08-25 at 12 19 35 AM

Code Here

/pages/catch

On this page we use some inferences to determine whether the
token was invalid (Valid tokens get added as a query param to the ws connection url).
We Successfully catch the issue and prevent further loading.
Screen Shot 2024-08-25 at 12 19 43 AM

Code Here

/pages/precatch

This page runs its own a fetch request to validate the token and determines whether we should bother attempting to connect.
Screen Shot 2024-08-25 at 12 19 55 AM

Code Here

/pages/fix-token

Even tho I have ways to catch bad tokens, I'm not sure how to fix it after the fact (easy to circumvent things with the precatch method before .connect() is triggered).

Code Here

Disconnect + Reconnect:

In this case, after detecting a bad token, we can see that disconnecting does not update client.live. For this reason, attempting to reconnect fails, nothing happens (subscribe errors but thats my fault).

console.log('live?', client.live)
console.log('disconnect...')
client.disconnect()
console.log('live2?', client.live)

setTimeout(()=>client.connect('ws://localhost:4000', 'project', undefined).then(()=>{
  console.log('attempt reconnect')
  console.log('live3?', client.live)
  // subscribe error is misleading, 
  // this just should not be done in .then()... my bad
  client.subscribe([
    "SELECT * FROM User",
    "SELECT * FROM Message"
  ])
}), 2e3)
Screen Shot 2024-08-25 at 7 28 11 PM

If we manually set client.live = false, we can start to get things working:

client.disconnect()
client.live = false
initToken = undefined // to pretend as though we never had a token
setTimeout(()=>client.connect('ws://localhost:4000', 'project', undefined), 1e3)

You can see we get a new Identity and every thing works as expected.
Screen Shot 2024-08-25 at 10 49 26 PM


Just Updating Client Properties:

I wont really go into depth on this as I do not know if this is a valid approach (there may be private fields I cannot update and idk if reducers will be called with the correct owner).

client.token = await gen_token(); //  from identity api
client?.['runtime']?.auth_token = client.token
client.identity = extract_id(client.token!); // from JWT
([window.global_token,window.global_identity] = [client.token, client.identity]); 

The downside here is that just updating fields wont run #[spacetimedb(connect)], the connect reducer. In this app, that means a user is not created for this new Identity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants