mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-04 01:18:20 +02:00
feat: exclude archived features in max reporting (#7559)
This commit is contained in:
parent
d9ae0f3f59
commit
3fe110f155
@ -7,12 +7,23 @@ export class FeatureStrategiesReadModel implements IFeatureStrategiesReadModel {
|
|||||||
constructor(db: Db) {
|
constructor(db: Db) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private activeStrategies() {
|
||||||
|
return this.db('feature_strategies')
|
||||||
|
.leftJoin(
|
||||||
|
'features',
|
||||||
|
'features.name',
|
||||||
|
'feature_strategies.feature_name',
|
||||||
|
)
|
||||||
|
.where('features.archived_at', null);
|
||||||
|
}
|
||||||
|
|
||||||
async getMaxFeatureEnvironmentStrategies(): Promise<{
|
async getMaxFeatureEnvironmentStrategies(): Promise<{
|
||||||
feature: string;
|
feature: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
count: number;
|
count: number;
|
||||||
} | null> {
|
} | null> {
|
||||||
const rows = await this.db('feature_strategies')
|
const rows = await this.activeStrategies()
|
||||||
.select('feature_name', 'environment')
|
.select('feature_name', 'environment')
|
||||||
.count('id as strategy_count')
|
.count('id as strategy_count')
|
||||||
.groupBy('feature_name', 'environment')
|
.groupBy('feature_name', 'environment')
|
||||||
@ -32,7 +43,7 @@ export class FeatureStrategiesReadModel implements IFeatureStrategiesReadModel {
|
|||||||
feature: string;
|
feature: string;
|
||||||
count: number;
|
count: number;
|
||||||
} | null> {
|
} | null> {
|
||||||
const rows = await this.db('feature_strategies')
|
const rows = await this.activeStrategies()
|
||||||
.select('feature_name')
|
.select('feature_name')
|
||||||
.count('id as strategy_count')
|
.count('id as strategy_count')
|
||||||
.groupBy('feature_name')
|
.groupBy('feature_name')
|
||||||
@ -52,7 +63,7 @@ export class FeatureStrategiesReadModel implements IFeatureStrategiesReadModel {
|
|||||||
environment: string;
|
environment: string;
|
||||||
count: number;
|
count: number;
|
||||||
} | null> {
|
} | null> {
|
||||||
const rows = await this.db('feature_strategies')
|
const rows = await this.activeStrategies()
|
||||||
.select(
|
.select(
|
||||||
'feature_name',
|
'feature_name',
|
||||||
'environment',
|
'environment',
|
||||||
@ -60,9 +71,9 @@ export class FeatureStrategiesReadModel implements IFeatureStrategiesReadModel {
|
|||||||
"MAX(coalesce(jsonb_array_length(constraint_value->'values'), 0)) as max_values_count",
|
"MAX(coalesce(jsonb_array_length(constraint_value->'values'), 0)) as max_values_count",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.from(
|
.crossJoin(
|
||||||
this.db.raw(
|
this.db.raw(
|
||||||
'feature_strategies, jsonb_array_elements(constraints) AS constraint_value',
|
`jsonb_array_elements(constraints) AS constraint_value`,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.groupBy('feature_name', 'environment')
|
.groupBy('feature_name', 'environment')
|
||||||
@ -77,12 +88,13 @@ export class FeatureStrategiesReadModel implements IFeatureStrategiesReadModel {
|
|||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMaxConstraintsPerStrategy(): Promise<{
|
async getMaxConstraintsPerStrategy(): Promise<{
|
||||||
feature: string;
|
feature: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
count: number;
|
count: number;
|
||||||
} | null> {
|
} | null> {
|
||||||
const rows = await this.db('feature_strategies')
|
const rows = await this.activeStrategies()
|
||||||
.select(
|
.select(
|
||||||
'feature_name',
|
'feature_name',
|
||||||
'environment',
|
'environment',
|
||||||
|
@ -5,6 +5,7 @@ import dbInit, {
|
|||||||
} from '../../../../test/e2e/helpers/database-init';
|
} from '../../../../test/e2e/helpers/database-init';
|
||||||
import getLogger from '../../../../test/fixtures/no-logger';
|
import getLogger from '../../../../test/fixtures/no-logger';
|
||||||
import type {
|
import type {
|
||||||
|
IConstraint,
|
||||||
IFeatureStrategiesReadModel,
|
IFeatureStrategiesReadModel,
|
||||||
IProjectStore,
|
IProjectStore,
|
||||||
IUnleashStores,
|
IUnleashStores,
|
||||||
@ -294,6 +295,32 @@ describe('max metrics collection', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const bigConstraint = (maxValueCount: number) => {
|
||||||
|
return {
|
||||||
|
values: Array.from({ length: maxValueCount }, (_, i) =>
|
||||||
|
i.toString(),
|
||||||
|
),
|
||||||
|
operator: 'IN',
|
||||||
|
contextName: 'appName',
|
||||||
|
} as const;
|
||||||
|
};
|
||||||
|
|
||||||
|
const strategyWithConstraints = (
|
||||||
|
feature: string,
|
||||||
|
constraint: IConstraint,
|
||||||
|
) => {
|
||||||
|
return {
|
||||||
|
strategyName: 'gradualRollout',
|
||||||
|
projectId: 'default',
|
||||||
|
environment: 'default',
|
||||||
|
featureName: feature,
|
||||||
|
constraints: [constraint],
|
||||||
|
|
||||||
|
sortOrder: 0,
|
||||||
|
parameters: {},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
test('Read feature with max number of constraint values', async () => {
|
test('Read feature with max number of constraint values', async () => {
|
||||||
const flagA = await featureToggleStore.create('default', {
|
const flagA = await featureToggleStore.create('default', {
|
||||||
name: randomId(),
|
name: randomId(),
|
||||||
@ -305,48 +332,33 @@ describe('max metrics collection', () => {
|
|||||||
createdByUserId: 9999,
|
createdByUserId: 9999,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const flagC = await featureToggleStore.create('default', {
|
||||||
|
name: randomId(),
|
||||||
|
createdByUserId: 9999,
|
||||||
|
});
|
||||||
|
|
||||||
const maxConstraintValuesBefore =
|
const maxConstraintValuesBefore =
|
||||||
await featureStrategiesReadModel.getMaxConstraintValues();
|
await featureStrategiesReadModel.getMaxConstraintValues();
|
||||||
expect(maxConstraintValuesBefore).toBe(null);
|
expect(maxConstraintValuesBefore).toBe(null);
|
||||||
|
|
||||||
const maxValueCount = 100;
|
const maxValueCount = 100;
|
||||||
await featureStrategiesStore.createStrategyFeatureEnv({
|
await featureStrategiesStore.createStrategyFeatureEnv(
|
||||||
strategyName: 'gradualRollout',
|
strategyWithConstraints(flagA.name, bigConstraint(maxValueCount)),
|
||||||
projectId: 'default',
|
);
|
||||||
environment: 'default',
|
await featureStrategiesStore.createStrategyFeatureEnv(
|
||||||
featureName: flagA.name,
|
strategyWithConstraints(flagB.name, {
|
||||||
constraints: [
|
operator: 'IN',
|
||||||
{
|
contextName: 'appName',
|
||||||
values: ['only one'],
|
}),
|
||||||
operator: 'IN',
|
);
|
||||||
contextName: 'appName',
|
await featureStrategiesStore.createStrategyFeatureEnv(
|
||||||
},
|
strategyWithConstraints(
|
||||||
{
|
flagC.name,
|
||||||
values: Array.from({ length: maxValueCount }, (_, i) =>
|
bigConstraint(maxValueCount + 1),
|
||||||
i.toString(),
|
),
|
||||||
),
|
);
|
||||||
operator: 'IN',
|
|
||||||
contextName: 'appName',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
sortOrder: 0,
|
await featureToggleStore.archive(flagC.name);
|
||||||
parameters: {},
|
|
||||||
});
|
|
||||||
await featureStrategiesStore.createStrategyFeatureEnv({
|
|
||||||
strategyName: 'gradualRollout',
|
|
||||||
projectId: 'default',
|
|
||||||
environment: 'default',
|
|
||||||
featureName: flagB.name,
|
|
||||||
constraints: [
|
|
||||||
{
|
|
||||||
operator: 'IN',
|
|
||||||
contextName: 'appName',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sortOrder: 0,
|
|
||||||
parameters: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
const maxConstraintValues =
|
const maxConstraintValues =
|
||||||
await featureStrategiesReadModel.getMaxConstraintValues();
|
await featureStrategiesReadModel.getMaxConstraintValues();
|
||||||
|
Loading…
Reference in New Issue
Block a user