mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-13 13:48:59 +02:00
Fix: only flexibleRollout strategy should use defaults
This commit is contained in:
parent
d56e88eef2
commit
8712bd17e9
@ -54,9 +54,7 @@ exports[`should match snapshot from /api/client/features 1`] = `
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
"name": "default",
|
"name": "default",
|
||||||
"parameters": {
|
"parameters": {},
|
||||||
"stickiness": "default",
|
|
||||||
},
|
|
||||||
"variants": [],
|
"variants": [],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -70,9 +70,7 @@ const getApiClientResponse = (project = 'default') => [
|
|||||||
values: ['123'],
|
values: ['123'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
parameters: {
|
parameters: {},
|
||||||
stickiness: 'default',
|
|
||||||
},
|
|
||||||
variants: [],
|
variants: [],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -117,7 +117,7 @@ import { sortStrategies } from '../../util/sortStrategies.js';
|
|||||||
import type { ResourceLimitsSchema } from '../../openapi/index.js';
|
import type { ResourceLimitsSchema } from '../../openapi/index.js';
|
||||||
import type FeatureLinkService from '../feature-links/feature-link-service.js';
|
import type FeatureLinkService from '../feature-links/feature-link-service.js';
|
||||||
import type { IFeatureLink } from '../feature-links/feature-links-read-model-type.js';
|
import type { IFeatureLink } from '../feature-links/feature-links-read-model-type.js';
|
||||||
|
import merge from 'deepmerge';
|
||||||
interface IFeatureContext {
|
interface IFeatureContext {
|
||||||
featureName: string;
|
featureName: string;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
@ -126,6 +126,9 @@ interface IFeatureContext {
|
|||||||
interface IFeatureStrategyContext extends IFeatureContext {
|
interface IFeatureStrategyContext extends IFeatureContext {
|
||||||
environment: string;
|
environment: string;
|
||||||
}
|
}
|
||||||
|
function mergeAll<T>(objects: Partial<T>[]): T {
|
||||||
|
return merge.all<T>(objects.filter((i) => i));
|
||||||
|
}
|
||||||
|
|
||||||
export interface IGetFeatureParams {
|
export interface IGetFeatureParams {
|
||||||
featureName: string;
|
featureName: string;
|
||||||
@ -670,7 +673,48 @@ export class FeatureToggleService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async standardizeStrategyConfig(
|
private async defaultParameters(
|
||||||
|
projectId: string,
|
||||||
|
strategyName: string,
|
||||||
|
featureName: string,
|
||||||
|
params: IFeatureStrategy['parameters'] | undefined,
|
||||||
|
) {
|
||||||
|
if (strategyName === 'flexibleRollout') {
|
||||||
|
if (params?.stickiness === '') {
|
||||||
|
// If stickiness is an empty string, we remove it to use the default stickiness.
|
||||||
|
delete params?.stickiness;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
rollout: '100',
|
||||||
|
stickiness:
|
||||||
|
params?.stickiness ??
|
||||||
|
(await this.featureStrategiesStore.getDefaultStickiness(
|
||||||
|
projectId,
|
||||||
|
)),
|
||||||
|
groupId: featureName,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
/// We don't really have good defaults for the other kinds of known strategies, so return an empty map.
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private async parametersWithDefaults(
|
||||||
|
projectId: string,
|
||||||
|
strategyName: string,
|
||||||
|
featureName: string,
|
||||||
|
params: IFeatureStrategy['parameters'] | undefined,
|
||||||
|
) {
|
||||||
|
return mergeAll([
|
||||||
|
await this.defaultParameters(
|
||||||
|
projectId,
|
||||||
|
strategyName,
|
||||||
|
featureName,
|
||||||
|
params,
|
||||||
|
),
|
||||||
|
params ?? {},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
private async standardizeStrategyConfig(
|
||||||
projectId: string,
|
projectId: string,
|
||||||
strategyConfig: Unsaved<IStrategyConfig>,
|
strategyConfig: Unsaved<IStrategyConfig>,
|
||||||
existing?: IFeatureStrategy,
|
existing?: IFeatureStrategy,
|
||||||
@ -695,18 +739,12 @@ export class FeatureToggleService {
|
|||||||
constraints = await this.validateConstraints(constraints);
|
constraints = await this.validateConstraints(constraints);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
parameters = await this.parametersWithDefaults(
|
||||||
parameters &&
|
projectId,
|
||||||
(!('stickiness' in parameters) ||
|
name,
|
||||||
('stickiness' in parameters && parameters.stickiness === ''))
|
strategyConfig.featureName!,
|
||||||
) {
|
strategyConfig.parameters,
|
||||||
parameters.stickiness =
|
);
|
||||||
existing?.parameters?.stickiness ||
|
|
||||||
(await this.featureStrategiesStore.getDefaultStickiness(
|
|
||||||
projectId,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (variants && variants.length > 0) {
|
if (variants && variants.length > 0) {
|
||||||
await variantsArraySchema.validateAsync(variants);
|
await variantsArraySchema.validateAsync(variants);
|
||||||
const fixedVariants = this.fixVariantWeights(variants);
|
const fixedVariants = this.fixVariantWeights(variants);
|
||||||
|
@ -28,7 +28,6 @@ import {
|
|||||||
import type { IFeatureProjectUserParams } from './feature-toggle-controller.js';
|
import type { IFeatureProjectUserParams } from './feature-toggle-controller.js';
|
||||||
import type { Db } from '../../db/db.js';
|
import type { Db } from '../../db/db.js';
|
||||||
import { isAfter } from 'date-fns';
|
import { isAfter } from 'date-fns';
|
||||||
import merge from 'deepmerge';
|
|
||||||
import Raw = Knex.Raw;
|
import Raw = Knex.Raw;
|
||||||
import type { ITag } from '../../tags/index.js';
|
import type { ITag } from '../../tags/index.js';
|
||||||
|
|
||||||
@ -157,32 +156,6 @@ function mapStrategyUpdate(
|
|||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeAll<T>(objects: Partial<T>[]): T {
|
|
||||||
return merge.all<T>(objects.filter((i) => i));
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultParameters = (
|
|
||||||
params: PartialSome<IFeatureStrategy, 'id' | 'createdAt'>,
|
|
||||||
stickiness: string,
|
|
||||||
) => {
|
|
||||||
if (params.strategyName === 'flexibleRollout') {
|
|
||||||
return {
|
|
||||||
rollout: '100',
|
|
||||||
stickiness,
|
|
||||||
groupId: params.featureName,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
/// We don't really have good defaults for the other kinds of known strategies, so return an empty map.
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const parametersWithDefaults = (
|
|
||||||
params: PartialSome<IFeatureStrategy, 'id' | 'createdAt'>,
|
|
||||||
stickiness: string,
|
|
||||||
) => {
|
|
||||||
return mergeAll([defaultParameters(params, stickiness), params.parameters]);
|
|
||||||
};
|
|
||||||
class FeatureStrategiesStore implements IFeatureStrategiesStore {
|
class FeatureStrategiesStore implements IFeatureStrategiesStore {
|
||||||
private db: Db;
|
private db: Db;
|
||||||
|
|
||||||
@ -264,13 +237,6 @@ class FeatureStrategiesStore implements IFeatureStrategiesStore {
|
|||||||
strategyConfig.featureName,
|
strategyConfig.featureName,
|
||||||
strategyConfig.environment,
|
strategyConfig.environment,
|
||||||
));
|
));
|
||||||
const stickiness =
|
|
||||||
strategyConfig.parameters?.stickiness ??
|
|
||||||
(await this.getDefaultStickiness(strategyConfig.projectId));
|
|
||||||
strategyConfig.parameters = parametersWithDefaults(
|
|
||||||
strategyConfig,
|
|
||||||
stickiness,
|
|
||||||
);
|
|
||||||
const strategyRow = mapInput({
|
const strategyRow = mapInput({
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
...strategyConfig,
|
...strategyConfig,
|
||||||
|
Loading…
Reference in New Issue
Block a user