From b617a846964ea49be2ffefd31439e911ad84ed8c Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Fri, 23 Aug 2024 12:16:19 +0100 Subject: [PATCH] All: Resolves #10407: Added feature flag to disable sync lock support (#10925) --- packages/lib/Synchronizer.ts | 1 + .../lib/models/settings/builtInMetadata.ts | 11 +++++++ .../lib/services/synchronizer/LockHandler.ts | 29 +++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/packages/lib/Synchronizer.ts b/packages/lib/Synchronizer.ts index afef7ac75..1812f25aa 100644 --- a/packages/lib/Synchronizer.ts +++ b/packages/lib/Synchronizer.ts @@ -131,6 +131,7 @@ export default class Synchronizer { public lockHandler() { if (this.lockHandler_) return this.lockHandler_; this.lockHandler_ = new LockHandler(this.api()); + this.lockHandler_.enabled = Setting.value('featureFlag.syncLockEnabled'); return this.lockHandler_; } diff --git a/packages/lib/models/settings/builtInMetadata.ts b/packages/lib/models/settings/builtInMetadata.ts index 84fd6f2d4..60916d7fb 100644 --- a/packages/lib/models/settings/builtInMetadata.ts +++ b/packages/lib/models/settings/builtInMetadata.ts @@ -1565,6 +1565,17 @@ const builtInMetadata = (Setting: typeof SettingType) => { isGlobal: true, }, + 'featureFlag.syncLockEnabled': { + value: true, + type: SettingItemType.Bool, + public: true, + storage: SettingStorage.File, + label: () => 'Enable sync locks', + description: () => 'This is an experimental setting to disable sync locks', + section: 'sync', + isGlobal: true, + }, + // 'featureFlag.syncAccurateTimestamps': { // value: false, diff --git a/packages/lib/services/synchronizer/LockHandler.ts b/packages/lib/services/synchronizer/LockHandler.ts index 2c0ee3854..9ce3017e9 100644 --- a/packages/lib/services/synchronizer/LockHandler.ts +++ b/packages/lib/services/synchronizer/LockHandler.ts @@ -26,6 +26,16 @@ export interface Lock { updatedTime?: number; } +const nullLock = (): Lock => { + return { + clientId: '', + clientType: LockClientType.Desktop, + type: LockType.None, + id: 'NULL_LOCK', + updatedTime: Date.now(), + }; +}; + function lockIsActive(lock: Lock, currentDate: Date, lockTtl: number): boolean { return currentDate.getTime() - lock.updatedTime < lockTtl; } @@ -140,6 +150,7 @@ export default class LockHandler { private refreshTimers_: RefreshTimers = {}; private autoRefreshInterval_: number = 1000 * 60; private lockTtl_: number = defaultLockTtl; + private enabled_ = true; public constructor(api: FileApi, options: LockHandlerOptions = null) { if (!options) options = {}; @@ -149,6 +160,14 @@ export default class LockHandler { if ('autoRefreshInterval' in options) this.autoRefreshInterval_ = options.autoRefreshInterval; } + public get enabled(): boolean { + return this.enabled_; + } + + public set enabled(v: boolean) { + this.enabled_ = v; + } + public get lockTtl(): number { return this.lockTtl_; } @@ -185,6 +204,8 @@ export default class LockHandler { } public async locks(lockType: LockType = null): Promise { + if (!this.enabled) return []; + if (this.useBuiltInLocks) { const locks = (await this.api_.listLocks()).items; return locks; @@ -352,6 +373,8 @@ export default class LockHandler { // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied public startAutoLockRefresh(lock: Lock, errorHandler: Function): string { + if (!this.enabled) return ''; + const handle = this.autoLockRefreshHandle(lock); if (this.refreshTimers_[handle]) { throw new Error(`There is already a timer refreshing this lock: ${handle}`); @@ -409,6 +432,8 @@ export default class LockHandler { } public stopAutoLockRefresh(lock: Lock) { + if (!this.enabled) return; + const handle = this.autoLockRefreshHandle(lock); if (!this.refreshTimers_[handle]) { // Should not throw an error because lock may have been cleared in startAutoLockRefresh @@ -422,6 +447,8 @@ export default class LockHandler { } public async acquireLock(lockType: LockType, clientType: LockClientType, clientId: string, options: AcquireLockOptions = null): Promise { + if (!this.enabled) return nullLock(); + options = { ...defaultAcquireLockOptions(), ...options, @@ -437,6 +464,8 @@ export default class LockHandler { } public async releaseLock(lockType: LockType, clientType: LockClientType, clientId: string) { + if (!this.enabled) return; + if (this.useBuiltInLocks) { await this.api_.releaseLock(lockType, clientType, clientId); return;