From 83c15a77c3dd3db0178fc8e104c69370c1496492 Mon Sep 17 00:00:00 2001 From: Andras Schmelczer Date: Sun, 23 Nov 2025 14:59:56 +0000 Subject: [PATCH] Add 2 more settings from consts --- frontend/sync-client/src/consts.ts | 7 +++--- .../sync-client/src/persistence/settings.ts | 6 ++++- .../sync-client/src/services/sync-service.ts | 7 +++--- frontend/sync-client/src/sync-client.ts | 25 +++++++++++-------- frontend/sync-client/src/utils/rate-limit.ts | 11 +++++--- 5 files changed, 34 insertions(+), 22 deletions(-) diff --git a/frontend/sync-client/src/consts.ts b/frontend/sync-client/src/consts.ts index 7dfe27ec..64f581f1 100644 --- a/frontend/sync-client/src/consts.ts +++ b/frontend/sync-client/src/consts.ts @@ -1,7 +1,6 @@ -export const NETWORK_RETRY_INTERVAL_MS = 1000; -export const MINIMUM_SAVE_INTERVAL_MS = 1000; +export const MERGABLE_FILE_TYPES = ["md", "txt"]; + +export const TIMEOUT_FOR_MERGING_HISTORY_ENTRIES_IN_SECONDS = 60; export const DIFF_CACHE_SIZE_MB = 2; export const MAX_LOG_MESSAGE_COUNT = 100000; export const MAX_HISTORY_ENTRY_COUNT = 5000; -export const TIMEOUT_FOR_MERGING_HISTORY_ENTRIES_IN_SECONDS = 60; -export const MERGABLE_FILE_TYPES = ["md", "txt"]; diff --git a/frontend/sync-client/src/persistence/settings.ts b/frontend/sync-client/src/persistence/settings.ts index 98c5c523..6ce4eeb5 100644 --- a/frontend/sync-client/src/persistence/settings.ts +++ b/frontend/sync-client/src/persistence/settings.ts @@ -11,6 +11,8 @@ export interface SyncSettings { webSocketRetryIntervalMs: number; diffCacheSizeMB: number; enableTelemetry: boolean; + networkRetryIntervalMs: number; + minimumSaveIntervalMs: number; } export const DEFAULT_SETTINGS: SyncSettings = { @@ -23,7 +25,9 @@ export const DEFAULT_SETTINGS: SyncSettings = { ignorePatterns: [], webSocketRetryIntervalMs: 3500, diffCacheSizeMB: 4, - enableTelemetry: false + enableTelemetry: false, + networkRetryIntervalMs: 1000, + minimumSaveIntervalMs: 1000 }; export class Settings { diff --git a/frontend/sync-client/src/services/sync-service.ts b/frontend/sync-client/src/services/sync-service.ts index 91d6f8df..c23fe95b 100644 --- a/frontend/sync-client/src/services/sync-service.ts +++ b/frontend/sync-client/src/services/sync-service.ts @@ -17,7 +17,6 @@ import type { FetchLatestDocumentsResponse } from "./types/FetchLatestDocumentsR import type { PingResponse } from "./types/PingResponse"; import type { DeleteDocumentVersion } from "./types/DeleteDocumentVersion"; import type { UpdateTextDocumentVersion } from "./types/UpdateTextDocumentVersion"; -import { NETWORK_RETRY_INTERVAL_MS } from "../consts"; export class SyncService { private readonly client: typeof globalThis.fetch; @@ -371,10 +370,12 @@ export class SyncService { throw e; } + const retryInterval = + this.settings.getSettings().networkRetryIntervalMs; this.logger.error( - `Failed network call (${e}), retrying in ${NETWORK_RETRY_INTERVAL_MS}ms` + `Failed network call (${e}), retrying in ${retryInterval}ms` ); - await sleep(NETWORK_RETRY_INTERVAL_MS); + await sleep(retryInterval); } } } diff --git a/frontend/sync-client/src/sync-client.ts b/frontend/sync-client/src/sync-client.ts index 56249e5b..26ebe168 100644 --- a/frontend/sync-client/src/sync-client.ts +++ b/frontend/sync-client/src/sync-client.ts @@ -24,7 +24,7 @@ import type { MaybeOutdatedClientCursors } from "./types/maybe-outdated-client-c import { FileChangeNotifier } from "./sync-operations/file-change-notifier"; import { FixedSizeDocumentCache } from "./utils/data-structures/fix-sized-cache"; import { setUpTelemetry } from "./utils/set-up-telemetry"; -import { DIFF_CACHE_SIZE_MB, MINIMUM_SAVE_INTERVAL_MS } from "./consts"; +import { DIFF_CACHE_SIZE_MB } from "./consts"; export class SyncClient { private hasStartedOfflineSync = false; @@ -157,9 +157,20 @@ export class SyncClient { database: undefined }; + const settings = new Settings( + logger, + state.settings, + async (data): Promise => { + state = { ...state, settings: data }; + // we're not rate-limiting settings saves as (1) we need to initialise the settings to know the rate limit + // and (2) settings changes are infrequent enough that rate-limiting is not necessary + await persistence.save(state); + } + ); + const rateLimitedSave = rateLimit( persistence.save, - MINIMUM_SAVE_INTERVAL_MS + () => settings.getSettings().minimumSaveIntervalMs ); const database = new Database( @@ -171,15 +182,6 @@ export class SyncClient { } ); - const settings = new Settings( - logger, - state.settings, - async (data): Promise => { - state = { ...state, settings: data }; - await rateLimitedSave(state); - } - ); - const fetchController = new FetchController( settings.getSettings().isSyncEnabled, logger @@ -201,6 +203,7 @@ export class SyncClient { const fileOperations = new FileOperations( logger, database, + settings, fs, nativeLineEndings ); diff --git a/frontend/sync-client/src/utils/rate-limit.ts b/frontend/sync-client/src/utils/rate-limit.ts index 4de89ae8..2c6d018b 100644 --- a/frontend/sync-client/src/utils/rate-limit.ts +++ b/frontend/sync-client/src/utils/rate-limit.ts @@ -10,7 +10,8 @@ import { sleep } from "./sleep"; * * @template T - Type of the function to be rate limited * @param {T} fn - The asynchronous function to rate limit - * @param {number} minIntervalMs - The minimum interval in milliseconds between function calls + * @param {number | (() => number)} minIntervalMs - Minimum interval in milliseconds between calls, + * or a function that returns the minimum interval * @returns {(...args: Parameters) => ReturnType | Promise} A decorated function that respects the rate limit. * Returns the original function's return type when executed, or undefined if the call was superseded by a newer one. */ @@ -21,7 +22,7 @@ export function rateLimit< ) => Promise >( fn: T, - minIntervalMs: number + minIntervalMs: number | (() => number) ): (...args: Parameters) => Promise { let newArgs: Parameters | undefined = undefined; let running: Promise | undefined = undefined; @@ -46,7 +47,11 @@ export function rateLimit< const [promise, resolve] = createPromise(); running = promise; - sleep(minIntervalMs) + sleep( + typeof minIntervalMs === "function" + ? minIntervalMs() + : minIntervalMs + ) .then(resolve) .catch(() => { // sleep cannot fail