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:
parent
239bf87b5c
commit
7229364b4a
@ -2,17 +2,27 @@ import { Knex } from 'knex';
|
|||||||
import metricsHelper from '../util/metrics-helper';
|
import metricsHelper from '../util/metrics-helper';
|
||||||
import { DB_TIME } from '../metric-events';
|
import { DB_TIME } from '../metric-events';
|
||||||
import { Logger, LogProvider } from '../logger';
|
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 { DEFAULT_ENV } from '../util/constants';
|
||||||
import { PartialDeep } from '../types/partial';
|
import { PartialDeep } from '../types/partial';
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
import FeatureToggleStore from './feature-toggle-store';
|
import FeatureToggleStore from './feature-toggle-store';
|
||||||
|
import { ensureStringValue } from '../util/ensureStringValue';
|
||||||
|
import { mapValues } from '../util/map-values';
|
||||||
import { Db } from './db';
|
import { Db } from './db';
|
||||||
|
import { IFeatureToggleAdminStore } from '../types/stores/feature-toggle-admin-store';
|
||||||
import Raw = Knex.Raw;
|
import Raw = Knex.Raw;
|
||||||
|
|
||||||
export interface IGetAllFeatures {
|
export interface IGetAllFeatures {
|
||||||
featureQuery?: IFeatureToggleQuery;
|
featureQuery?: IFeatureToggleQuery;
|
||||||
archived: boolean;
|
archived: boolean;
|
||||||
|
includeStrategyIds?: boolean;
|
||||||
userId?: number;
|
userId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,9 +32,9 @@ export interface IGetAdminFeatures {
|
|||||||
userId?: number;
|
userId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is extracted from the feature-toggle-client-store that was mixing
|
export default class FeatureToggleAdminStore
|
||||||
// client and admin concerns
|
implements IFeatureToggleAdminStore
|
||||||
export default class FeatureToggleAdminStore {
|
{
|
||||||
private db: Db;
|
private db: Db;
|
||||||
|
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
@ -36,7 +46,7 @@ export default class FeatureToggleAdminStore {
|
|||||||
this.logger = getLogger('feature-toggle-admin-store.ts');
|
this.logger = getLogger('feature-toggle-admin-store.ts');
|
||||||
this.timer = (action) =>
|
this.timer = (action) =>
|
||||||
metricsHelper.wrapTimer(eventBus, DB_TIME, {
|
metricsHelper.wrapTimer(eventBus, DB_TIME, {
|
||||||
store: 'admin-feature-toggle',
|
store: 'feature-toggle',
|
||||||
action,
|
action,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -45,7 +55,7 @@ export default class FeatureToggleAdminStore {
|
|||||||
featureQuery,
|
featureQuery,
|
||||||
archived,
|
archived,
|
||||||
userId,
|
userId,
|
||||||
}: IGetAllFeatures): Promise<FeatureToggle[]> {
|
}: IGetAllFeatures): Promise<(IFeatureToggleClient & FeatureToggle)[]> {
|
||||||
const environment = featureQuery?.environment || DEFAULT_ENV;
|
const environment = featureQuery?.environment || DEFAULT_ENV;
|
||||||
const stopTimer = this.timer('getFeatureAdmin');
|
const stopTimer = this.timer('getFeatureAdmin');
|
||||||
|
|
||||||
@ -152,9 +162,28 @@ export default class FeatureToggleAdminStore {
|
|||||||
stopTimer();
|
stopTimer();
|
||||||
|
|
||||||
const featureToggles = rows.reduce((acc, r) => {
|
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.impressionData = r.impression_data;
|
||||||
|
feature.enabled = !!r.enabled;
|
||||||
feature.name = r.name;
|
feature.name = r.name;
|
||||||
feature.description = r.description;
|
feature.description = r.description;
|
||||||
feature.project = r.project;
|
feature.project = r.project;
|
||||||
@ -169,16 +198,90 @@ export default class FeatureToggleAdminStore {
|
|||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const features: FeatureToggle[] = Object.values(featureToggles);
|
const features: IFeatureToggleClient[] = Object.values(featureToggles);
|
||||||
|
|
||||||
return features;
|
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({
|
async getAdmin({
|
||||||
featureQuery,
|
featureQuery,
|
||||||
userId,
|
userId,
|
||||||
archived,
|
archived,
|
||||||
}: IGetAdminFeatures): Promise<FeatureToggle[]> {
|
}: IGetAdminFeatures): Promise<IFeatureToggleClient[]> {
|
||||||
return this.getAll({ featureQuery, archived, userId });
|
return this.getAll({ featureQuery, archived, userId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user