From c76c8f135a11b68be4347ea922cd4100af405e4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20Conradi=20=C3=98sthus?= Date: Sat, 3 Feb 2024 07:30:22 +0100 Subject: [PATCH] Fix/check maintenance flag once per minute (#6118) ## About the changes Every schedule job will now check if maintenance is enabled. This ends up querying the settings table in the db at least once per second per running unleash instance. This small fix caches this query for 60 seconds to reduce the load somewhat. We should reconsider this solution for the long term, but this will be a great improvement on the short term. **Logs after this fix running locally.** We can observe that we resolve settings from the DB once per minute. ![image](https://github.com/Unleash/unleash/assets/158948/c313cf38-8d86-4b86-a0ba-4f4df60d50d6) Also we should consider giving a warning in section where you enable maintenance mode that it can take up to a minute to propagate. --- .../features/maintenance/maintenance-service.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/lib/features/maintenance/maintenance-service.ts b/src/lib/features/maintenance/maintenance-service.ts index 8748a0e1eec7..5e2fa6c881cc 100644 --- a/src/lib/features/maintenance/maintenance-service.ts +++ b/src/lib/features/maintenance/maintenance-service.ts @@ -1,8 +1,10 @@ +import memoizee from 'memoizee'; import { IUnleashConfig } from '../../types'; import { Logger } from '../../logger'; import SettingService from '../../services/setting-service'; import { maintenanceSettingsKey } from '../../types/settings/maintenance-settings'; import { MaintenanceSchema } from '../../openapi/spec/maintenance-schema'; +import { minutesToMilliseconds } from 'date-fns'; export interface IMaintenanceStatus { isMaintenanceMode(): Promise; @@ -15,20 +17,30 @@ export default class MaintenanceService implements IMaintenanceStatus { private settingService: SettingService; + private resolveMaintenance: () => Promise; + constructor(config: IUnleashConfig, settingService: SettingService) { this.config = config; this.logger = config.getLogger('services/maintenance-service.ts'); this.settingService = settingService; + this.resolveMaintenance = memoizee( + async () => (await this.getMaintenanceSetting()).enabled, + { + promise: true, + maxAge: minutesToMilliseconds(1), + }, + ); } async isMaintenanceMode(): Promise { return ( this.config.flagResolver.isEnabled('maintenanceMode') || - (await this.getMaintenanceSetting()).enabled + (await this.resolveMaintenance()) ); } async getMaintenanceSetting(): Promise { + this.logger.debug('getMaintenanceSetting called'); return ( (await this.settingService.get(maintenanceSettingsKey)) || { enabled: false, @@ -41,6 +53,8 @@ export default class MaintenanceService implements IMaintenanceStatus { user: string, toggledByUserId: number, ): Promise { + //@ts-ignore + this.resolveMaintenance.clear(); return this.settingService.insert( maintenanceSettingsKey, setting,