1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-31 00:16:47 +01:00

refactor: Extract playground steps (#3966)

This commit is contained in:
Mateusz Kwasniewski 2023-06-13 11:26:10 +02:00 committed by GitHub
parent 8daab71219
commit 7d69750f3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 23 deletions

View File

@ -7,7 +7,7 @@ export const splitByComma = <T extends Record<string, string>>(
Object.entries(obj).map(([key, value]) => [key, value.split(',')]), Object.entries(obj).map(([key, value]) => [key, value.split(',')]),
) as Dict<T>; ) as Dict<T>;
export const generateCombinations = <T extends Record<string, string>>( export const generateCombinations = <T extends Record<string, any>>(
obj: Dict<T>, obj: Dict<T>,
): T[] => { ): T[] => {
const keys = Object.keys(obj) as (keyof T)[]; const keys = Object.keys(obj) as (keyof T)[];
@ -21,7 +21,7 @@ export const generateCombinations = <T extends Record<string, string>>(
) as T[]; ) as T[];
}; };
export const generateObjectCombinations = <T extends Record<string, string>>( export const generateObjectCombinations = <T extends Record<string, any>>(
obj: T, obj: T,
): T[] => { ): T[] => {
const splitObj = splitByComma(obj); const splitObj = splitByComma(obj);

View File

@ -64,7 +64,7 @@ export const offlineUnleashClient = async ({
}, },
}); });
client.start(); await client.start();
return client; return client;
}; };

View File

@ -4,11 +4,20 @@ import { IUnleashServices } from 'lib/types/services';
import { ALL } from '../../types/models/api-token'; import { ALL } from '../../types/models/api-token';
import { PlaygroundFeatureSchema } from 'lib/openapi/spec/playground-feature-schema'; import { PlaygroundFeatureSchema } from 'lib/openapi/spec/playground-feature-schema';
import { Logger } from '../../logger'; import { Logger } from '../../logger';
import { IUnleashConfig } from 'lib/types'; import { ISegment, IUnleashConfig } from 'lib/types';
import { offlineUnleashClient } from './offline-unleash-client'; import { offlineUnleashClient } from './offline-unleash-client';
import { FeatureInterface } from 'lib/features/playground/feature-evaluator/feature'; import { FeatureInterface } from 'lib/features/playground/feature-evaluator/feature';
import { FeatureStrategiesEvaluationResult } from 'lib/features/playground/feature-evaluator/client'; import { FeatureStrategiesEvaluationResult } from 'lib/features/playground/feature-evaluator/client';
import { ISegmentService } from 'lib/segments/segment-service-interface'; import { ISegmentService } from 'lib/segments/segment-service-interface';
import { FeatureConfigurationClient } from '../../types/stores/feature-strategies-store';
import { generateObjectCombinations } from './generateObjectCombinations';
type EvaluationInput = {
features: FeatureConfigurationClient[];
segments: ISegment[];
featureProject: Record<string, string>;
context: SdkContextSchema;
};
export class PlaygroundService { export class PlaygroundService {
private readonly logger: Logger; private readonly logger: Logger;
@ -29,30 +38,38 @@ export class PlaygroundService {
this.segmentService = segmentService; this.segmentService = segmentService;
} }
async evaluateQuery( async evaluateAdvancedQuery(
projects: typeof ALL | string[], projects: typeof ALL | string[],
environment: string, environments: string[],
context: SdkContextSchema, context: SdkContextSchema,
): Promise<PlaygroundFeatureSchema[]> { ): Promise<PlaygroundFeatureSchema[]> {
const [features, segments] = await Promise.all([ const segments = await this.segmentService.getActive();
this.featureToggleService.getClientFeatures( const environmentFeatures = await Promise.all(
{ environments.map((env) => this.resolveFeatures(projects, env)),
project: projects === ALL ? undefined : projects,
environment,
},
true,
false,
),
this.segmentService.getActive(),
]);
const featureProject: Record<string, string> = features.reduce(
(obj, feature) => {
obj[feature.name] = feature.project;
return obj;
},
{},
); );
const contexts = generateObjectCombinations(context);
const results = await Promise.all(
environmentFeatures.flatMap(({ features, featureProject }) =>
contexts.map((singleContext) =>
this.evaluate({
features,
featureProject,
context: singleContext,
segments,
}),
),
),
);
return results.flat();
}
private async evaluate({
featureProject,
features,
segments,
context,
}: EvaluationInput): Promise<PlaygroundFeatureSchema[]> {
const [head, ...rest] = features; const [head, ...rest] = features;
if (!head) { if (!head) {
return []; return [];
@ -102,4 +119,39 @@ export class PlaygroundService {
return output; return output;
} }
} }
private async resolveFeatures(
projects: typeof ALL | string[],
environment: string,
): Promise<Pick<EvaluationInput, 'features' | 'featureProject'>> {
const features = await this.featureToggleService.getClientFeatures(
{
project: projects === ALL ? undefined : projects,
environment,
},
true,
false,
);
const featureProject: Record<string, string> = features.reduce(
(obj, feature) => {
obj[feature.name] = feature.project;
return obj;
},
{},
);
return { features, featureProject };
}
async evaluateQuery(
projects: typeof ALL | string[],
environment: string,
context: SdkContextSchema,
): Promise<PlaygroundFeatureSchema[]> {
const [{ features, featureProject }, segments] = await Promise.all([
this.resolveFeatures(projects, environment),
this.segmentService.getActive(),
]);
return this.evaluate({ features, featureProject, segments, context });
}
} }