1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-10 17:53:36 +02:00

feat: admin store returns extra data for segments tests

This commit is contained in:
kwasniew 2023-03-09 12:00:52 +01:00
parent 239bf87b5c
commit 7229364b4a
No known key found for this signature in database
GPG Key ID: 43A7CBC24C119560

View File

@ -2,17 +2,27 @@ import { Knex } from 'knex';
import metricsHelper from '../util/metrics-helper';
import { DB_TIME } from '../metric-events';
import { Logger, LogProvider } from '../logger';
import { FeatureToggle, IFeatureToggleQuery } from '../types/model';
import {
FeatureToggle,
IFeatureToggleClient,
IFeatureToggleQuery,
IStrategyConfig,
ITag,
} from '../types/model';
import { DEFAULT_ENV } from '../util/constants';
import { PartialDeep } from '../types/partial';
import EventEmitter from 'events';
import FeatureToggleStore from './feature-toggle-store';
import { ensureStringValue } from '../util/ensureStringValue';
import { mapValues } from '../util/map-values';
import { Db } from './db';
import { IFeatureToggleAdminStore } from '../types/stores/feature-toggle-admin-store';
import Raw = Knex.Raw;
export interface IGetAllFeatures {
featureQuery?: IFeatureToggleQuery;
archived: boolean;
includeStrategyIds?: boolean;
userId?: number;
}
@ -22,9 +32,9 @@ export interface IGetAdminFeatures {
userId?: number;
}
// This is extracted from the feature-toggle-client-store that was mixing
// client and admin concerns
export default class FeatureToggleAdminStore {
export default class FeatureToggleAdminStore
implements IFeatureToggleAdminStore
{
private db: Db;
private logger: Logger;
@ -36,7 +46,7 @@ export default class FeatureToggleAdminStore {
this.logger = getLogger('feature-toggle-admin-store.ts');
this.timer = (action) =>
metricsHelper.wrapTimer(eventBus, DB_TIME, {
store: 'admin-feature-toggle',
store: 'feature-toggle',
action,
});
}
@ -45,7 +55,7 @@ export default class FeatureToggleAdminStore {
featureQuery,
archived,
userId,
}: IGetAllFeatures): Promise<FeatureToggle[]> {
}: IGetAllFeatures): Promise<(IFeatureToggleClient & FeatureToggle)[]> {
const environment = featureQuery?.environment || DEFAULT_ENV;
const stopTimer = this.timer('getFeatureAdmin');
@ -152,9 +162,28 @@ export default class FeatureToggleAdminStore {
stopTimer();
const featureToggles = rows.reduce((acc, r) => {
let feature: PartialDeep<FeatureToggle> = acc[r.name] ?? {};
let feature: PartialDeep<IFeatureToggleClient & FeatureToggle> =
acc[r.name] ?? {
strategies: [],
};
if (this.isUnseenStrategyRow(feature, r)) {
feature.strategies.push(
FeatureToggleAdminStore.rowToStrategy(r),
);
}
if (this.isNewTag(feature, r)) {
this.addTag(feature, r);
}
if (featureQuery?.inlineSegmentConstraints && r.segment_id) {
this.addSegmentToStrategy(feature, r);
} else if (
!featureQuery?.inlineSegmentConstraints &&
r.segment_id
) {
this.addSegmentIdsToStrategy(feature, r);
}
feature.impressionData = r.impression_data;
feature.enabled = !!r.enabled;
feature.name = r.name;
feature.description = r.description;
feature.project = r.project;
@ -169,16 +198,90 @@ export default class FeatureToggleAdminStore {
return acc;
}, {});
const features: FeatureToggle[] = Object.values(featureToggles);
const features: IFeatureToggleClient[] = Object.values(featureToggles);
return features;
}
private static rowToStrategy(row: Record<string, any>): IStrategyConfig {
return {
id: row.strategy_id,
name: row.strategy_name,
constraints: row.constraints || [],
parameters: mapValues(row.parameters || {}, ensureStringValue),
};
}
private static rowToTag(row: Record<string, any>): ITag {
return {
value: row.tag_value,
type: row.tag_type,
};
}
private isUnseenStrategyRow(
feature: PartialDeep<IFeatureToggleClient>,
row: Record<string, any>,
): boolean {
return (
row.strategy_id &&
!feature.strategies.find((s) => s.id === row.strategy_id)
);
}
private addTag(
feature: Record<string, any>,
row: Record<string, any>,
): void {
const tags = feature.tags || [];
const newTag = FeatureToggleAdminStore.rowToTag(row);
feature.tags = [...tags, newTag];
}
private isNewTag(
feature: PartialDeep<IFeatureToggleClient>,
row: Record<string, any>,
): boolean {
return (
row.tag_type &&
row.tag_value &&
!feature.tags?.some(
(tag) =>
tag.type === row.tag_type && tag.value === row.tag_value,
)
);
}
private addSegmentToStrategy(
feature: PartialDeep<IFeatureToggleClient>,
row: Record<string, any>,
) {
feature.strategies
.find((s) => s.id === row.strategy_id)
?.constraints.push(...row.segment_constraints);
}
private addSegmentIdsToStrategy(
feature: PartialDeep<IFeatureToggleClient>,
row: Record<string, any>,
) {
const strategy = feature.strategies.find(
(s) => s.id === row.strategy_id,
);
if (!strategy) {
return;
}
if (!strategy.segments) {
strategy.segments = [];
}
strategy.segments.push(row.segment_id);
}
async getAdmin({
featureQuery,
userId,
archived,
}: IGetAdminFeatures): Promise<FeatureToggle[]> {
}: IGetAdminFeatures): Promise<IFeatureToggleClient[]> {
return this.getAll({ featureQuery, archived, userId });
}
}