websockets icon indicating copy to clipboard operation
websockets copied to clipboard

Allow for custom exponential backoff in websocket client

Open jakubno opened this issue 2 years ago • 5 comments

Custom exponential backoff

In asyncio client, there was introduced option to use an infinite asynchronous iterator to reconnect automatically on errors, more in docs.

There were set constants for exponential backoff: client.py. But it's too slow for my use case. I would like to shorten it and I would prefer some cleaner way than this:

auto_reconnect = websockets.connect(...)
auto_reconnect.BACKOFF_INITIAL = 1
async for websocket in auto_reconnect:
    try:
        ...
    except websockets.ConnectionClosed:
        continue

Ideally it should be a parameter of the connect function.

jakubno avatar Aug 27 '23 14:08 jakubno

I declared these constants as class variables because, somehow, I know that someone would want to adjust them, even if that involved a private API :-)

FYI I expected the following pattern:


websockets.connect.BACKOFF_INITIAL = 1
async for websocket in websockets.connect(...):
    ...

If you're OK with changing the timeout for all uses of connect() in your program, this avoids the convoluted pattern that you've shown.


The obvious answer is to add Yet Another Parameter in the signature of connect(). However, this API has too many parameters already: currently 17. In fact, it would be 4 additional parameters if we want to make everything customizable.

I'm slightly resisting the addition of new parameters because simplicity is a design goal of websockets. More parameters mean overhead in the docs for everyone...

Maybe I have to bite the bullet and move all parameters to a configuration object. Or just live with so many parameters. I'm not sure yet.

Since your request is "public API guaranteed to be stable", I want to be confident that I have the right API before committing to it. I don't feel ready to make this call right now :-/

aaugustin avatar Oct 01 '23 14:10 aaugustin

Sure, your pattern looks way better :) Thanks for your explanation!

jakubno avatar Oct 01 '23 15:10 jakubno

In case someone else has the same need -- please leave a comment and I'm likely to reopen the issue!

The request for a public API is legitimate, even if I'm not sure how to handle it.

aaugustin avatar Oct 01 '23 15:10 aaugustin

It looks like this is a little trickier now with the async rewrite, since the constants are the module level rather than inside a class now. Since I'm distributing a client where it's not easy to set env vars, I think my options are

  • set env vars in code, then do a runtime import of websockets. Risky since we could accidentally add an import elsewhere
  • monkeypatch the backoff fn, which is also brittle.

Adding a public api would be lovely. Two reasonable options would either be adding each of the max_backoff, min_backoff etc. as params, or allow passing in a custom backoff fn

johannkm avatar Aug 26 '25 20:08 johannkm

OK - let's do something about this.

aaugustin avatar Aug 27 '25 07:08 aaugustin