1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-06-04 01:18:20 +02:00

fix: improve status job performance (#9755)

This commit is contained in:
Mateusz Kwasniewski 2025-04-15 09:33:13 +02:00 committed by GitHub
parent fc40a4b4d8
commit 0efa2585fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 23 additions and 12 deletions

View File

@ -117,6 +117,7 @@ class ProjectStatsStore implements IProjectStatsStore {
async getTimeToProdDates(
projectId: string,
): Promise<ICreateEnabledDates[]> {
const stopTimer = this.timer('getTimeToProdDates');
const result = await this.db
.select('events.feature_name')
// select only first enabled event, distinct works with orderBy
@ -143,6 +144,7 @@ class ProjectStatsStore implements IProjectStatsStore {
.orderBy('events.feature_name')
// first enabled event
.orderBy('events.created_at', 'asc');
stopTimer();
return result;
}

View File

@ -89,6 +89,9 @@ import type EventEmitter from 'events';
import type { ApiTokenService } from '../../services/api-token-service';
import type { ProjectForUi } from './project-read-model-type';
import { canGrantProjectRole } from './can-grant-project-role';
import { batchExecute } from '../../util/batchExecute';
import metricsHelper from '../../util/metrics-helper';
import { FUNCTION_TIME } from '../../metric-events';
type Days = number;
type Count = number;
@ -167,6 +170,8 @@ export default class ProjectService {
private onboardingReadModel: IOnboardingReadModel;
private timer: Function;
constructor(
{
projectStore,
@ -226,6 +231,11 @@ export default class ProjectService {
this.eventBus = config.eventBus;
this.projectReadModel = projectReadModel;
this.onboardingReadModel = onboardingReadModel;
this.timer = (functionName: string) =>
metricsHelper.wrapTimer(config.eventBus, FUNCTION_TIME, {
className: 'ProjectService',
functionName,
});
}
async getProjects(
@ -1282,21 +1292,18 @@ export default class ProjectService {
async statusJob(): Promise<void> {
const projects = await this.projectStore.getAll();
const statusUpdates = await Promise.all(
projects.map((project) => this.getStatusUpdates(project.id)),
);
await Promise.all(
statusUpdates.map((statusUpdate) => {
return this.projectStatsStore.updateProjectStats(
// run one project status update at a time every
void batchExecute(projects, 1, 30_000, async (project) => {
const statusUpdate = await this.getStatusUpdates(project.id);
await this.projectStatsStore.updateProjectStats(
statusUpdate.projectId,
statusUpdate.updates,
);
}),
);
});
}
async getStatusUpdates(projectId: string): Promise<ICalculateStatus> {
const stopTimer = this.timer('getStatusUpdates');
const dateMinusThirtyDays = subDays(new Date(), 30).toISOString();
const dateMinusSixtyDays = subDays(new Date(), 60).toISOString();
@ -1370,6 +1377,7 @@ export default class ProjectService {
dateMinusThirtyDays,
);
stopTimer();
return {
projectId,
updates: {

View File

@ -30,3 +30,4 @@ export * from './arraysHaveSameItems';
export * from './constantTimeCompare';
export * from '../features/metrics/client-metrics/collapseHourlyMetrics';
export * from '../features/playground/offline-unleash-client';
export * from './batchExecute';