Skip to content

Conversation

@EhabY
Copy link
Collaborator

@EhabY EhabY commented Nov 17, 2025

Closes #595

This PR implements a reconnecting WebSocket with exponential backoff that automatically uses the most up-to-date authentication information.

Why not use existing packages?

Third-party reconnecting WebSocket packages (e.g., reconnecting-websocket) were considered but don't meet our requirements:

  • Most packages are stale/unmaintained
  • None support custom async authentication methods (we pass different options based on header commands or session tokens)
  • Limited flexibility for future authentication expansion

Additional features:

  • Automatic reconnection when session tokens or host values change, ensuring we always use current authentication info
  • Potential future enhancement: Reconnect on proxy/auth/header setting changes (deferred for now)

@EhabY EhabY force-pushed the reconnecting-websockets branch 4 times, most recently from f10c59b to 656bb4c Compare November 21, 2025 09:49
Comment on lines 193 to 191
// Don't reconnect on normal closure
if (event.code === 1000 || event.code === 1001) {
return;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: magic numbers are magic.. const these?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines +56 to +59
if (watcher.error !== undefined) {
watcher.error = undefined;
onChange.fire(null);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the context behind this change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we reach this place in the code that means we didn't encounter an error while parsing the message and thus we have a valid message so we clear the error (if any). The clients of this method usually display the error (if it exists) before attempting to access the value

Comment on lines +55 to +62
initialBackoffMs: options.initialBackoffMs ?? 250,
maxBackoffMs: options.maxBackoffMs ?? 30000,
jitterFactor: options.jitterFactor ?? 0.1,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did we come up with these default values? This is non-blocking, just curious 😄

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh very random and some AI "researched" values hahaha

wasClean: true,
type: "close",
target: this.#currentSocket,
} as CloseEvent);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need as CloseEvent? Could we make use of satisfies?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out, this exposed a bigger issue with types, I made sure to narrow the types in eventStreamConnection so it's reflects the information we have and we don't do some nasty casting

Copy link
Collaborator

@DanielleMaywood DanielleMaywood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy with this change, thanks for addressing the types issue 🙏

@EhabY EhabY force-pushed the reconnecting-websockets branch from eec4c99 to 55b793b Compare November 25, 2025 09:57
@EhabY EhabY merged commit d5c3cc0 into coder:main Nov 25, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add automatic WebSocket reconnection with exponential backoff

3 participants