mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-26 01:17:00 +02:00
refactor: segment-store getAll refactor, move mappers out of main method. (#6423)
For `getAll` method, kept only sql queries and moved mappers into separate functions. No change in logic, just refactoring.
This commit is contained in:
parent
f3df7269cb
commit
ce8e15347c
@ -18,13 +18,11 @@ import { DashboardHeader } from './components/DashboardHeader/DashboardHeader';
|
||||
import { UserStats } from './componentsStat/UserStats/UserStats';
|
||||
import { FlagStats } from './componentsStat/FlagStats/FlagStats';
|
||||
import { HealthStats } from './componentsStat/HealthStats/HealthStats';
|
||||
import { TimeToProduction } from './componentsStat/TimeToProduction/TimeToProduction';
|
||||
|
||||
import { UsersChart } from './componentsChart/UsersChart/UsersChart';
|
||||
import { FlagsChart } from './componentsChart/FlagsChart/FlagsChart';
|
||||
import { FlagsProjectChart } from './componentsChart/FlagsProjectChart/FlagsProjectChart';
|
||||
import { ProjectHealthChart } from './componentsChart/ProjectHealthChart/ProjectHealthChart';
|
||||
import { TimeToProductionChart } from './componentsChart/TimeToProductionChart/TimeToProductionChart';
|
||||
import { MetricsSummaryChart } from './componentsChart/MetricsSummaryChart/MetricsSummaryChart';
|
||||
import { UsersPerProjectChart } from './componentsChart/UsersPerProjectChart/UsersPerProjectChart';
|
||||
|
||||
|
@ -116,141 +116,172 @@ export default class SegmentStore implements ISegmentStore {
|
||||
includeChangeRequestUsageData: boolean = false,
|
||||
): Promise<ISegment[]> {
|
||||
if (includeChangeRequestUsageData) {
|
||||
const pendingCRs = await this.db
|
||||
.select('id', 'project')
|
||||
.from('change_requests')
|
||||
.whereNotIn('state', ['Applied', 'Rejected', 'Cancelled']);
|
||||
return this.getAllWithChangeRequestUsageData();
|
||||
} else {
|
||||
return this.getAllWithoutChangeRequestUsageData();
|
||||
}
|
||||
}
|
||||
|
||||
const pendingChangeRequestIds = pendingCRs.map((cr) => cr.id);
|
||||
private async getAllWithoutChangeRequestUsageData(): Promise<ISegment[]> {
|
||||
const rows: ISegmentRow[] = await this.db
|
||||
.select(
|
||||
this.prefixColumns(),
|
||||
'used_in_projects',
|
||||
'used_in_features',
|
||||
)
|
||||
.countDistinct(
|
||||
`${T.featureStrategies}.project_name AS used_in_projects`,
|
||||
)
|
||||
.countDistinct(
|
||||
`${T.featureStrategies}.feature_name AS used_in_features`,
|
||||
)
|
||||
.from(T.segments)
|
||||
.leftJoin(
|
||||
T.featureStrategySegment,
|
||||
`${T.segments}.id`,
|
||||
`${T.featureStrategySegment}.segment_id`,
|
||||
)
|
||||
.leftJoin(
|
||||
T.featureStrategies,
|
||||
`${T.featureStrategies}.id`,
|
||||
`${T.featureStrategySegment}.feature_strategy_id`,
|
||||
)
|
||||
.groupBy(this.prefixColumns())
|
||||
.orderBy('name', 'asc');
|
||||
|
||||
const crFeatures = await this.db
|
||||
.select(
|
||||
'payload',
|
||||
'feature',
|
||||
'change_request_id as changeRequestId',
|
||||
)
|
||||
.from('change_request_events')
|
||||
.whereIn('change_request_id', pendingChangeRequestIds)
|
||||
.whereIn('action', ['addStrategy', 'updateStrategy'])
|
||||
.andWhereRaw("jsonb_array_length(payload -> 'segments') > 0");
|
||||
return rows.map(this.mapRow);
|
||||
}
|
||||
|
||||
const changeRequestToProjectMap = pendingCRs.reduce(
|
||||
(acc, { id, project }) => {
|
||||
acc[id] = project;
|
||||
return acc;
|
||||
},
|
||||
{},
|
||||
private async getAllWithChangeRequestUsageData(): Promise<ISegment[]> {
|
||||
const pendingCRs = await this.db
|
||||
.select('id', 'project')
|
||||
.from('change_requests')
|
||||
.whereNotIn('state', ['Applied', 'Rejected', 'Cancelled']);
|
||||
|
||||
const pendingChangeRequestIds = pendingCRs.map((cr) => cr.id);
|
||||
|
||||
const crFeatures = await this.db
|
||||
.select(
|
||||
'payload',
|
||||
'feature',
|
||||
'change_request_id as changeRequestId',
|
||||
)
|
||||
.from('change_request_events')
|
||||
.whereIn('change_request_id', pendingChangeRequestIds)
|
||||
.whereIn('action', ['addStrategy', 'updateStrategy'])
|
||||
.andWhereRaw("jsonb_array_length(payload -> 'segments') > 0");
|
||||
|
||||
const combinedUsageData = this.combineUsageData(pendingCRs, crFeatures);
|
||||
|
||||
const currentSegmentUsage = await this.db
|
||||
.select(
|
||||
`${T.featureStrategies}.feature_name as featureName`,
|
||||
`${T.featureStrategies}.project_name as projectName`,
|
||||
'segment_id as segmentId',
|
||||
)
|
||||
.from(T.featureStrategySegment)
|
||||
.leftJoin(
|
||||
T.featureStrategies,
|
||||
`${T.featureStrategies}.id`,
|
||||
`${T.featureStrategySegment}.feature_strategy_id`,
|
||||
);
|
||||
|
||||
const combinedUsageData = crFeatures.reduce((acc, segmentEvent) => {
|
||||
const { payload, changeRequestId, feature } = segmentEvent;
|
||||
const project = changeRequestToProjectMap[changeRequestId];
|
||||
this.mergeCurrentUsageWithCombinedData(
|
||||
combinedUsageData,
|
||||
currentSegmentUsage,
|
||||
);
|
||||
|
||||
for (const segmentId of payload.segments) {
|
||||
const existingData = acc[segmentId];
|
||||
if (existingData) {
|
||||
acc[segmentId] = {
|
||||
features: existingData.features.add(feature),
|
||||
projects: existingData.projects.add(project),
|
||||
};
|
||||
} else {
|
||||
acc[segmentId] = {
|
||||
features: new Set([feature]),
|
||||
projects: new Set([project]),
|
||||
};
|
||||
}
|
||||
}
|
||||
const rows: ISegmentRow[] = await this.db
|
||||
.select(this.prefixColumns())
|
||||
.from(T.segments)
|
||||
.leftJoin(
|
||||
T.featureStrategySegment,
|
||||
`${T.segments}.id`,
|
||||
`${T.featureStrategySegment}.segment_id`,
|
||||
)
|
||||
.groupBy(this.prefixColumns())
|
||||
.orderBy('name', 'asc');
|
||||
|
||||
const rowsWithUsageData = this.mapRowsWithUsageData(
|
||||
rows,
|
||||
combinedUsageData,
|
||||
);
|
||||
|
||||
return rowsWithUsageData.map(this.mapRow);
|
||||
}
|
||||
|
||||
private mapRowsWithUsageData(
|
||||
rows: ISegmentRow[],
|
||||
combinedUsageData: any,
|
||||
): ISegmentRow[] {
|
||||
return rows.map((row) => {
|
||||
const usageData = combinedUsageData[row.id];
|
||||
if (usageData) {
|
||||
return {
|
||||
...row,
|
||||
used_in_features: usageData.features.size,
|
||||
used_in_projects: usageData.projects.size,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...row,
|
||||
used_in_features: 0,
|
||||
used_in_projects: 0,
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private combineUsageData = (pendingCRs, crFeatures) => {
|
||||
const changeRequestToProjectMap = pendingCRs.reduce(
|
||||
(acc, { id, project }) => {
|
||||
acc[id] = project;
|
||||
return acc;
|
||||
}, {});
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
const currentSegmentUsage = await this.db
|
||||
.select(
|
||||
`${T.featureStrategies}.feature_name as featureName`,
|
||||
`${T.featureStrategies}.project_name as projectName`,
|
||||
'segment_id as segmentId',
|
||||
)
|
||||
.from(T.featureStrategySegment)
|
||||
.leftJoin(
|
||||
T.featureStrategies,
|
||||
`${T.featureStrategies}.id`,
|
||||
`${T.featureStrategySegment}.feature_strategy_id`,
|
||||
);
|
||||
const combinedUsageData = crFeatures.reduce((acc, segmentEvent) => {
|
||||
const { payload, changeRequestId, feature } = segmentEvent;
|
||||
const project = changeRequestToProjectMap[changeRequestId];
|
||||
|
||||
currentSegmentUsage.forEach(
|
||||
({ segmentId, featureName, projectName }) => {
|
||||
const usage = combinedUsageData[segmentId];
|
||||
if (usage) {
|
||||
combinedUsageData[segmentId] = {
|
||||
features: usage.features.add(featureName),
|
||||
projects: usage.projects.add(projectName),
|
||||
};
|
||||
} else {
|
||||
combinedUsageData[segmentId] = {
|
||||
features: new Set([featureName]),
|
||||
projects: new Set([projectName]),
|
||||
};
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const rows: ISegmentRow[] = await this.db
|
||||
.select(this.prefixColumns())
|
||||
.from(T.segments)
|
||||
.leftJoin(
|
||||
T.featureStrategySegment,
|
||||
`${T.segments}.id`,
|
||||
`${T.featureStrategySegment}.segment_id`,
|
||||
)
|
||||
.groupBy(this.prefixColumns())
|
||||
.orderBy('name', 'asc');
|
||||
|
||||
const rowsWithUsageData: ISegmentRow[] = rows.map((row) => {
|
||||
const usageData = combinedUsageData[row.id];
|
||||
if (usageData) {
|
||||
return {
|
||||
...row,
|
||||
used_in_features: usageData.features.size,
|
||||
used_in_projects: usageData.projects.size,
|
||||
for (const segmentId of payload.segments) {
|
||||
const existingData = acc[segmentId];
|
||||
if (existingData) {
|
||||
acc[segmentId] = {
|
||||
features: existingData.features.add(feature),
|
||||
projects: existingData.projects.add(project),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...row,
|
||||
used_in_features: 0,
|
||||
used_in_projects: 0,
|
||||
acc[segmentId] = {
|
||||
features: new Set([feature]),
|
||||
projects: new Set([project]),
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
return combinedUsageData;
|
||||
};
|
||||
|
||||
return rowsWithUsageData.map(this.mapRow);
|
||||
} else {
|
||||
const rows: ISegmentRow[] = await this.db
|
||||
.select(
|
||||
this.prefixColumns(),
|
||||
'used_in_projects',
|
||||
'used_in_features',
|
||||
)
|
||||
.countDistinct(
|
||||
`${T.featureStrategies}.project_name AS used_in_projects`,
|
||||
)
|
||||
.countDistinct(
|
||||
`${T.featureStrategies}.feature_name AS used_in_features`,
|
||||
)
|
||||
.from(T.segments)
|
||||
.leftJoin(
|
||||
T.featureStrategySegment,
|
||||
`${T.segments}.id`,
|
||||
`${T.featureStrategySegment}.segment_id`,
|
||||
)
|
||||
.leftJoin(
|
||||
T.featureStrategies,
|
||||
`${T.featureStrategies}.id`,
|
||||
`${T.featureStrategySegment}.feature_strategy_id`,
|
||||
)
|
||||
.groupBy(this.prefixColumns())
|
||||
.orderBy('name', 'asc');
|
||||
|
||||
return rows.map(this.mapRow);
|
||||
}
|
||||
private mergeCurrentUsageWithCombinedData(
|
||||
combinedUsageData: any,
|
||||
currentSegmentUsage: any[],
|
||||
) {
|
||||
currentSegmentUsage.forEach(
|
||||
({ segmentId, featureName, projectName }) => {
|
||||
const usage = combinedUsageData[segmentId];
|
||||
if (usage) {
|
||||
usage.features.add(featureName);
|
||||
usage.projects.add(projectName);
|
||||
} else {
|
||||
combinedUsageData[segmentId] = {
|
||||
features: new Set([featureName]),
|
||||
projects: new Set([projectName]),
|
||||
};
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async getActive(): Promise<ISegment[]> {
|
||||
|
Loading…
Reference in New Issue
Block a user