Skip to content

Commit

Permalink
feat: exclude archived features in max reporting (#7559)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwasniew authored Jul 10, 2024
1 parent d9ae0f3 commit 3fe110f
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 42 deletions.
24 changes: 18 additions & 6 deletions src/lib/features/feature-toggle/feature-strategies-read-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,23 @@ export class FeatureStrategiesReadModel implements IFeatureStrategiesReadModel {
constructor(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<{
feature: string;
environment: string;
count: number;
} | null> {
const rows = await this.db('feature_strategies')
const rows = await this.activeStrategies()
.select('feature_name', 'environment')
.count('id as strategy_count')
.groupBy('feature_name', 'environment')
Expand All @@ -32,7 +43,7 @@ export class FeatureStrategiesReadModel implements IFeatureStrategiesReadModel {
feature: string;
count: number;
} | null> {
const rows = await this.db('feature_strategies')
const rows = await this.activeStrategies()
.select('feature_name')
.count('id as strategy_count')
.groupBy('feature_name')
Expand All @@ -52,17 +63,17 @@ export class FeatureStrategiesReadModel implements IFeatureStrategiesReadModel {
environment: string;
count: number;
} | null> {
const rows = await this.db('feature_strategies')
const rows = await this.activeStrategies()
.select(
'feature_name',
'environment',
this.db.raw(
"MAX(coalesce(jsonb_array_length(constraint_value->'values'), 0)) as max_values_count",
),
)
.from(
.crossJoin(
this.db.raw(
'feature_strategies, jsonb_array_elements(constraints) AS constraint_value',
`jsonb_array_elements(constraints) AS constraint_value`,
),
)
.groupBy('feature_name', 'environment')
Expand All @@ -77,12 +88,13 @@ export class FeatureStrategiesReadModel implements IFeatureStrategiesReadModel {
}
: null;
}

async getMaxConstraintsPerStrategy(): Promise<{
feature: string;
environment: string;
count: number;
} | null> {
const rows = await this.db('feature_strategies')
const rows = await this.activeStrategies()
.select(
'feature_name',
'environment',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import dbInit, {
} from '../../../../test/e2e/helpers/database-init';
import getLogger from '../../../../test/fixtures/no-logger';
import type {
IConstraint,
IFeatureStrategiesReadModel,
IProjectStore,
IUnleashStores,
Expand Down Expand Up @@ -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 () => {
const flagA = await featureToggleStore.create('default', {
name: randomId(),
Expand All @@ -305,48 +332,33 @@ describe('max metrics collection', () => {
createdByUserId: 9999,
});

const flagC = await featureToggleStore.create('default', {
name: randomId(),
createdByUserId: 9999,
});

const maxConstraintValuesBefore =
await featureStrategiesReadModel.getMaxConstraintValues();
expect(maxConstraintValuesBefore).toBe(null);

const maxValueCount = 100;
await featureStrategiesStore.createStrategyFeatureEnv({
strategyName: 'gradualRollout',
projectId: 'default',
environment: 'default',
featureName: flagA.name,
constraints: [
{
values: ['only one'],
operator: 'IN',
contextName: 'appName',
},
{
values: Array.from({ length: maxValueCount }, (_, i) =>
i.toString(),
),
operator: 'IN',
contextName: 'appName',
},
],
await featureStrategiesStore.createStrategyFeatureEnv(
strategyWithConstraints(flagA.name, bigConstraint(maxValueCount)),
);
await featureStrategiesStore.createStrategyFeatureEnv(
strategyWithConstraints(flagB.name, {
operator: 'IN',
contextName: 'appName',
}),
);
await featureStrategiesStore.createStrategyFeatureEnv(
strategyWithConstraints(
flagC.name,
bigConstraint(maxValueCount + 1),
),
);

sortOrder: 0,
parameters: {},
});
await featureStrategiesStore.createStrategyFeatureEnv({
strategyName: 'gradualRollout',
projectId: 'default',
environment: 'default',
featureName: flagB.name,
constraints: [
{
operator: 'IN',
contextName: 'appName',
},
],
sortOrder: 0,
parameters: {},
});
await featureToggleStore.archive(flagC.name);

const maxConstraintValues =
await featureStrategiesReadModel.getMaxConstraintValues();
Expand Down

0 comments on commit 3fe110f

Please sign in to comment.