Skip to content

Commit

Permalink
Improve cloud variable backoff logic
Browse files Browse the repository at this point in the history
Our cloud variable server refuses connections when there are too many people in
the same room. The client does have backoff logic, however that backoff counter
is being reset when the connection is initially opened, even if the connection
is immediately closed for being over capacity.

These way these interact gives a spectacular failure case. Say that there's
2000 people playing a project with cloud variables. Let's say that about 100 of
them are let in. The other 1900 clients will be constantly opening connections,
trying to get in. Those numbers are made up but it should illustrate the
problem.

To fix this we'll wait a bit before resetting the backoff counter, to make sure
that the server didn't refuse the connection. There are cleaner ways to fix
this problem, but this solution doesn't require protocol changes.
  • Loading branch information
GarboMuffin committed Nov 3, 2024
1 parent 857dc10 commit 5e923f3
Showing 1 changed file with 15 additions and 3 deletions.
18 changes: 15 additions & 3 deletions src/lib/cloud-provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class CloudProvider {
this.cloudHost = cloudHost;

this.connectionAttempts = 0;
this._resetConnectionAttemptsTimeout = null;

// A queue of messages to send which were received before the
// connection was ready
Expand Down Expand Up @@ -81,9 +82,11 @@ class CloudProvider {
}

onOpen () {
// Reset connection attempts to 1 to make sure any subsequent reconnects
// use connectionAttempts=1 to calculate timeout
this.connectionAttempts = 1;
this._resetConnectionAttemptsTimeout = setTimeout(() => {
this.connectionAttempts = 0;
this._resetConnectionAttemptsTimeout = null;
}, 10 * 1000);

this.writeToServer('handshake');
log.info(`Successfully connected to clouddata server.`);

Expand All @@ -97,6 +100,11 @@ class CloudProvider {
}

onClose (e) {
if (this._resetConnectionAttemptsTimeout) {
clearTimeout(this._resetConnectionAttemptsTimeout);
this._resetConnectionAttemptsTimeout = null;
}

// tw: code 4002 is "Username Error" -- do not try to reconnect
if (e && e.code === 4002) {
log.info('Cloud username is invalid. Not reconnecting.');
Expand Down Expand Up @@ -251,6 +259,10 @@ class CloudProvider {
clearTimeout(this._connectionTimeout);
this._connectionTimeout = null;
}
if (this._resetConnectionAttemptsTimeout) {
clearTimeout(this._resetConnectionAttemptsTimeout);
this._resetConnectionAttemptsTimeout = null;
}
this.connectionAttempts = 0;
}

Expand Down

0 comments on commit 5e923f3

Please sign in to comment.