Skip to content

Commit

Permalink
Dexie-cloud addon websocket client-side rate-limits:
Browse files Browse the repository at this point in the history
Decrease pause period from 10 to 1 second when more than 10 WebSocket messages per 10 seconds limit is reached.
+ simplify the loop + make it confifurable with const variables in top of the module.
Remove the panic pause of one minute if getting into the limit over and over. Instead let it do it but at most 10 messages per second.
If we see this becoming a problem we could enforce a limit on the server instead.
  • Loading branch information
dfahlander committed May 29, 2024
1 parent a09b699 commit fdd9844
Showing 1 changed file with 9 additions and 14 deletions.
23 changes: 9 additions & 14 deletions addons/dexie-cloud/src/sync/messagesFromServerQueue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import { updateBaseRevs } from './updateBaseRevs';
import { getLatestRevisionsPerTable } from './getLatestRevisionsPerTable';
import { refreshAccessToken } from '../authentication/authenticate';

const LIMIT_NUM_MESSAGES_PER_TIME = 10; // Allow a maximum of 10 messages per...
const TIME_WINDOW = 10_000; // ...10 seconds.
const PAUSE_PERIOD = 1_000; // Pause for 1 second if reached

export type MessagesFromServerConsumer = ReturnType<
typeof MessagesFromServerConsumer
>;
Expand All @@ -25,8 +29,7 @@ export function MessagesFromServerConsumer(db: DexieCloudDB) {
const event = new BehaviorSubject(null);
let isWorking = false;

let loopWarning = 0;
let loopDetection = [0, 0, 0, 0, 0, 0, 0, 0, 0, Date.now()];
let loopDetection = new Array(LIMIT_NUM_MESSAGES_PER_TIME).fill(0);

event.subscribe(async () => {
if (isWorking) return;
Expand All @@ -40,20 +43,12 @@ export function MessagesFromServerConsumer(db: DexieCloudDB) {
} finally {
if (
loopDetection[loopDetection.length - 1] - loopDetection[0] <
10000
TIME_WINDOW
) {
// Ten loops within 10 seconds. Slow down!
if (Date.now() - loopWarning < 5000) {
// Last time we did this, we ended up here too. Wait for a minute.
console.warn(`Slowing down websocket loop for one minute`);
loopWarning = Date.now() + 60000;
await new Promise((resolve) => setTimeout(resolve, 60000));
} else {
// This is a one-time event. Just pause 10 seconds.
console.warn(`Slowing down websocket loop for 10 seconds`);
loopWarning = Date.now() + 10000;
await new Promise((resolve) => setTimeout(resolve, 10000));
}
// This is a one-time event. Just pause 10 seconds.
console.warn(`Slowing down websocket loop for ${PAUSE_PERIOD} milliseconds`);
await new Promise((resolve) => setTimeout(resolve, PAUSE_PERIOD));
}
isWorking = false;
readyToServe.next(true);
Expand Down

0 comments on commit fdd9844

Please sign in to comment.