mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: remove inactive applications (#9835)
This commit is contained in:
		
							parent
							
								
									bffaab5560
								
							
						
					
					
						commit
						d24bcff404
					
				@ -449,4 +449,16 @@ export default class ClientApplicationsStore
 | 
				
			|||||||
            }));
 | 
					            }));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async removeInactiveApplications(): Promise<number> {
 | 
				
			||||||
 | 
					        const rows = await this.db(TABLE)
 | 
				
			||||||
 | 
					            .whereRaw("seen_at < now() - interval '30 days'")
 | 
				
			||||||
 | 
					            .del();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (rows > 0) {
 | 
				
			||||||
 | 
					            this.logger.debug(`Deleted ${rows} applications`);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return rows;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -298,6 +298,13 @@ export default class ClientInstanceService {
 | 
				
			|||||||
        return this.clientInstanceStore.removeInstancesOlderThanTwoDays();
 | 
					        return this.clientInstanceStore.removeInstancesOlderThanTwoDays();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async removeInactiveApplications(): Promise<number> {
 | 
				
			||||||
 | 
					        if (this.flagResolver.isEnabled('removeInactiveApplications')) {
 | 
				
			||||||
 | 
					            return this.clientApplicationsStore.removeInactiveApplications();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async getOutdatedSdks(): Promise<OutdatedSdksSchema['sdks']> {
 | 
					    async getOutdatedSdks(): Promise<OutdatedSdksSchema['sdks']> {
 | 
				
			||||||
        const sdkApps = await this.clientInstanceStore.groupApplicationsBySdk();
 | 
					        const sdkApps = await this.clientInstanceStore.groupApplicationsBySdk();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -78,6 +78,14 @@ export const scheduleServices = async (
 | 
				
			|||||||
        'removeInstancesOlderThanTwoDays',
 | 
					        'removeInstancesOlderThanTwoDays',
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    schedulerService.schedule(
 | 
				
			||||||
 | 
					        clientInstanceService.removeInactiveApplications.bind(
 | 
				
			||||||
 | 
					            clientInstanceService,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        hoursToMilliseconds(24),
 | 
				
			||||||
 | 
					        'removeInactiveApplications',
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    schedulerService.schedule(
 | 
					    schedulerService.schedule(
 | 
				
			||||||
        clientInstanceService.bulkAdd.bind(clientInstanceService),
 | 
					        clientInstanceService.bulkAdd.bind(clientInstanceService),
 | 
				
			||||||
        secondsToMilliseconds(5),
 | 
					        secondsToMilliseconds(5),
 | 
				
			||||||
 | 
				
			|||||||
@ -69,7 +69,8 @@ export type IFlagKey =
 | 
				
			|||||||
    | 'newStrategyDropdown'
 | 
					    | 'newStrategyDropdown'
 | 
				
			||||||
    | 'flagsOverviewSearch'
 | 
					    | 'flagsOverviewSearch'
 | 
				
			||||||
    | 'flagsReleaseManagementUI'
 | 
					    | 'flagsReleaseManagementUI'
 | 
				
			||||||
    | 'cleanupReminder';
 | 
					    | 'cleanupReminder'
 | 
				
			||||||
 | 
					    | 'removeInactiveApplications';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
 | 
					export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -330,6 +331,10 @@ const flags: IFlags = {
 | 
				
			|||||||
        process.env.UNLEASH_EXPERIMENTAL_CLEANUP_REMINDER,
 | 
					        process.env.UNLEASH_EXPERIMENTAL_CLEANUP_REMINDER,
 | 
				
			||||||
        false,
 | 
					        false,
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
 | 
					    removeInactiveApplications: parseEnvVarBoolean(
 | 
				
			||||||
 | 
					        process.env.UNLEASH_EXPERIMENTAL_REMOVE_INACTIVE_APPLICATIONS,
 | 
				
			||||||
 | 
					        false,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const defaultExperimentalOptions: IExperimentalOptions = {
 | 
					export const defaultExperimentalOptions: IExperimentalOptions = {
 | 
				
			||||||
 | 
				
			|||||||
@ -44,4 +44,5 @@ export interface IClientApplicationsStore
 | 
				
			|||||||
    getUnannounced(): Promise<IClientApplication[]>;
 | 
					    getUnannounced(): Promise<IClientApplication[]>;
 | 
				
			||||||
    setUnannouncedToAnnounced(): Promise<IClientApplication[]>;
 | 
					    setUnannouncedToAnnounced(): Promise<IClientApplication[]>;
 | 
				
			||||||
    getApplicationOverview(appName: string): Promise<IApplicationOverview>;
 | 
					    getApplicationOverview(appName: string): Promise<IApplicationOverview>;
 | 
				
			||||||
 | 
					    removeInactiveApplications(): Promise<number>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@ import type {
 | 
				
			|||||||
    IUnleashStores,
 | 
					    IUnleashStores,
 | 
				
			||||||
} from '../../../lib/types';
 | 
					} from '../../../lib/types';
 | 
				
			||||||
import type { IClientApplication } from '../../../lib/types/stores/client-applications-store';
 | 
					import type { IClientApplication } from '../../../lib/types/stores/client-applications-store';
 | 
				
			||||||
 | 
					import { subDays } from 'date-fns';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let db: ITestDb;
 | 
					let db: ITestDb;
 | 
				
			||||||
let stores: IUnleashStores;
 | 
					let stores: IUnleashStores;
 | 
				
			||||||
@ -175,3 +176,33 @@ test('Multi row merge also works', async () => {
 | 
				
			|||||||
        expect(s!.icon).toBe('red');
 | 
					        expect(s!.icon).toBe('red');
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test('Remove inactive applications', async () => {
 | 
				
			||||||
 | 
					    const clientRegistration = {
 | 
				
			||||||
 | 
					        appName: faker.internet.domainName(),
 | 
				
			||||||
 | 
					        instanceId: faker.datatype.uuid(),
 | 
				
			||||||
 | 
					        strategies: ['default'],
 | 
				
			||||||
 | 
					        started: Date.now(),
 | 
				
			||||||
 | 
					        interval: faker.datatype.number(),
 | 
				
			||||||
 | 
					        sdkVersion: '3.11.2',
 | 
				
			||||||
 | 
					        icon: '',
 | 
				
			||||||
 | 
					        description: faker.company.catchPhrase(),
 | 
				
			||||||
 | 
					        color: faker.internet.color(),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await clientApplicationsStore.upsert({
 | 
				
			||||||
 | 
					        ...clientRegistration,
 | 
				
			||||||
 | 
					        lastSeen: subDays(Date.now(), 29),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    const noRemovedItems =
 | 
				
			||||||
 | 
					        await clientApplicationsStore.removeInactiveApplications();
 | 
				
			||||||
 | 
					    expect(noRemovedItems).toBe(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await clientApplicationsStore.upsert({
 | 
				
			||||||
 | 
					        ...clientRegistration,
 | 
				
			||||||
 | 
					        lastSeen: subDays(Date.now(), 30),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    const removedItems =
 | 
				
			||||||
 | 
					        await clientApplicationsStore.removeInactiveApplications();
 | 
				
			||||||
 | 
					    expect(removedItems).toBe(1);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -82,4 +82,8 @@ export default class FakeClientApplicationsStore
 | 
				
			|||||||
    getApplicationOverview(appName: string): Promise<IApplicationOverview> {
 | 
					    getApplicationOverview(appName: string): Promise<IApplicationOverview> {
 | 
				
			||||||
        throw new Error('Method not implemented.');
 | 
					        throw new Error('Method not implemented.');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async removeInactiveApplications(): Promise<number> {
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user