Skip to content

Commit

Permalink
Fix/check maintenance flag once per minute (#6118)
Browse files Browse the repository at this point in the history
## 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.
  • Loading branch information
ivarconr authored Feb 3, 2024
1 parent 7b04db0 commit c76c8f1
Showing 1 changed file with 15 additions and 1 deletion.
16 changes: 15 additions & 1 deletion src/lib/features/maintenance/maintenance-service.ts
Original file line number Diff line number Diff line change
@@ -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<boolean>;
Expand All @@ -15,20 +17,30 @@ export default class MaintenanceService implements IMaintenanceStatus {

private settingService: SettingService;

private resolveMaintenance: () => Promise<boolean>;

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<boolean> {
return (
this.config.flagResolver.isEnabled('maintenanceMode') ||
(await this.getMaintenanceSetting()).enabled
(await this.resolveMaintenance())
);
}

async getMaintenanceSetting(): Promise<MaintenanceSchema> {
this.logger.debug('getMaintenanceSetting called');
return (
(await this.settingService.get(maintenanceSettingsKey)) || {
enabled: false,
Expand All @@ -41,6 +53,8 @@ export default class MaintenanceService implements IMaintenanceStatus {
user: string,
toggledByUserId: number,
): Promise<void> {
//@ts-ignore
this.resolveMaintenance.clear();
return this.settingService.insert(
maintenanceSettingsKey,
setting,
Expand Down

0 comments on commit c76c8f1

Please sign in to comment.