diff --git a/frontend/sync-client/src/file-operations/safe-filesystem-operations.ts b/frontend/sync-client/src/file-operations/safe-filesystem-operations.ts index fc0a1ed5..3bd84266 100644 --- a/frontend/sync-client/src/file-operations/safe-filesystem-operations.ts +++ b/frontend/sync-client/src/file-operations/safe-filesystem-operations.ts @@ -17,7 +17,7 @@ export class SafeFileSystemOperations implements FileSystemOperations { private readonly fs: FileSystemOperations, private readonly logger: Logger ) { - this.locks = new Locks(logger); + this.locks = new Locks(SafeFileSystemOperations.name, logger); } public async listFilesRecursively( diff --git a/frontend/sync-client/src/persistence/settings.ts b/frontend/sync-client/src/persistence/settings.ts index d78170e6..9771b7f1 100644 --- a/frontend/sync-client/src/persistence/settings.ts +++ b/frontend/sync-client/src/persistence/settings.ts @@ -38,7 +38,7 @@ export class Settings { >(); private settings: SyncSettings; - private readonly lock: Lock = new Lock(); + private readonly lock: Lock; public constructor( private readonly logger: Logger, @@ -50,6 +50,8 @@ export class Settings { ...(initialState ?? {}) }; + this.lock = new Lock(Settings.name, this.logger); + this.logger.debug( `Loaded settings: ${JSON.stringify(this.settings, null, 2)}` ); diff --git a/frontend/sync-client/src/sync-operations/cursor-tracker.ts b/frontend/sync-client/src/sync-operations/cursor-tracker.ts index 48b8908a..b4f4991c 100644 --- a/frontend/sync-client/src/sync-operations/cursor-tracker.ts +++ b/frontend/sync-client/src/sync-operations/cursor-tracker.ts @@ -22,7 +22,7 @@ export class CursorTracker { (cursors: MaybeOutdatedClientCursors[]) => unknown >(); - private readonly updateLock = new Lock(); + private readonly updateLock = new Lock(CursorTracker.name); private knownRemoteCursors: (ClientCursors & { upToDateness: DocumentUpToDateness; diff --git a/frontend/sync-client/src/utils/data-structures/locks.test.ts b/frontend/sync-client/src/utils/data-structures/locks.test.ts index 163f970f..1ea633cc 100644 --- a/frontend/sync-client/src/utils/data-structures/locks.test.ts +++ b/frontend/sync-client/src/utils/data-structures/locks.test.ts @@ -18,7 +18,7 @@ describe("withLock", () => { let locks: Locks; beforeEach(() => { - locks = new Locks(logger); + locks = new Locks("locks-test", logger); }); it("should execute function with single key lock", async () => { @@ -253,7 +253,7 @@ describe("reset", () => { let locks: Locks; beforeEach(() => { - locks = new Locks(logger); + locks = new Locks("locks-test", logger); }); it("should reject pending waiters with SyncResetError while running operation completes", async () => { @@ -265,7 +265,7 @@ describe("reset", () => { await sleep(1); const secondPromise = locks.withLock(testPath, async () => "second"); - void secondPromise.catch(() => {}); // eslint-disable-line @typescript-eslint/no-empty-function + void secondPromise.catch(() => { }); // eslint-disable-line @typescript-eslint/no-empty-function locks.reset(); @@ -286,7 +286,7 @@ describe("reset", () => { await sleep(1); const secondPromise = locks.withLock(testPath, async () => "second"); - void secondPromise.catch(() => {}); // eslint-disable-line @typescript-eslint/no-empty-function + void secondPromise.catch(() => { }); // eslint-disable-line @typescript-eslint/no-empty-function locks.reset(); @@ -312,7 +312,7 @@ describe("reset", () => { [testPath, testPath2], async () => "multi" ); - void multiKeyPromise.catch(() => {}); // eslint-disable-line @typescript-eslint/no-empty-function + void multiKeyPromise.catch(() => { }); // eslint-disable-line @typescript-eslint/no-empty-function // Wait for the multi-key operation to acquire testPath and start waiting on testPath2 await sleep(10); diff --git a/frontend/sync-client/src/utils/data-structures/locks.ts b/frontend/sync-client/src/utils/data-structures/locks.ts index 740757e7..4e512869 100644 --- a/frontend/sync-client/src/utils/data-structures/locks.ts +++ b/frontend/sync-client/src/utils/data-structures/locks.ts @@ -20,7 +20,7 @@ export class Locks { /** Queue of waiters for each key */ private readonly waiters = new Map[]>(); - public constructor(private readonly logger?: Logger) { } + public constructor(private readonly name: string, private readonly logger?: Logger) { } /** * Executes a function while holding exclusive locks on one or more keys. @@ -122,7 +122,7 @@ export class Locks { return Promise.resolve(); } - this.logger?.debug(`Waiting for lock on ${key}`); + this.logger?.debug(`Waiting for lock '${this.name}' on '${key}'`); return new Promise((resolve, reject) => { // DefaultDict behavior @@ -149,18 +149,18 @@ export class Locks { public unlock(key: T): void { if (!this.locked.has(key)) { this.logger?.debug( - `Attempted to unlock ${key} which is not locked` + `Attempted to unlock '${this.name}' on '${key}' which is not locked` ); return; } - this.logger?.debug(`Releasing lock on ${key}`); + this.logger?.debug(`Releasing lock '${this.name}' on '${key}'`); // Remove first waiter to ensure FIFO order const nextWaiter = this.waiters.get(key)?.shift(); if (nextWaiter) { - this.logger?.debug(`Granted lock on ${key}`); + this.logger?.debug(`Granted lock '${this.name}' on '${key}'`); nextWaiter.resolve(); } else { this.locked.delete(key); @@ -171,8 +171,8 @@ export class Locks { export class Lock { private readonly locks: Locks; - public constructor(logger?: Logger) { - this.locks = new Locks(logger); + public constructor(name: string, logger?: Logger) { + this.locks = new Locks(name, logger); } public async withLock(fn: () => R | Promise): Promise { diff --git a/frontend/sync-client/src/utils/debugging/slow-web-socket-factory.ts b/frontend/sync-client/src/utils/debugging/slow-web-socket-factory.ts index c64bff18..b93460b5 100644 --- a/frontend/sync-client/src/utils/debugging/slow-web-socket-factory.ts +++ b/frontend/sync-client/src/utils/debugging/slow-web-socket-factory.ts @@ -11,7 +11,7 @@ export function slowWebSocketFactory( private static readonly RECEIVE_KEY = "websocket-receive"; private static readonly SEND_KEY = "websocket-send"; - private readonly locks = new Locks(logger); + private readonly locks = new Locks(FlakyWebSocket.name, logger); public set onopen(callback: ((event: Event) => void) | null) { super.onopen = async (event: Event): Promise => {