Skip to content

Commit

Permalink
refactor: Extract playground steps (#3966)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwasniew committed Jun 13, 2023
1 parent 8daab71 commit 7d69750
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 22 deletions.
Expand Up @@ -7,7 +7,7 @@ export const splitByComma = <T extends Record<string, string>>(
Object.entries(obj).map(([key, value]) => [key, value.split(',')]),
) as Dict<T>;

export const generateCombinations = <T extends Record<string, string>>(
export const generateCombinations = <T extends Record<string, any>>(
obj: Dict<T>,
): T[] => {
const keys = Object.keys(obj) as (keyof T)[];
Expand All @@ -21,7 +21,7 @@ export const generateCombinations = <T extends Record<string, string>>(
) as T[];
};

export const generateObjectCombinations = <T extends Record<string, string>>(
export const generateObjectCombinations = <T extends Record<string, any>>(
obj: T,
): T[] => {
const splitObj = splitByComma(obj);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/features/playground/offline-unleash-client.ts
Expand Up @@ -64,7 +64,7 @@ export const offlineUnleashClient = async ({
},
});

client.start();
await client.start();

return client;
};
90 changes: 71 additions & 19 deletions src/lib/features/playground/playground-service.ts
Expand Up @@ -4,11 +4,20 @@ import { IUnleashServices } from 'lib/types/services';
import { ALL } from '../../types/models/api-token';
import { PlaygroundFeatureSchema } from 'lib/openapi/spec/playground-feature-schema';
import { Logger } from '../../logger';
import { IUnleashConfig } from 'lib/types';
import { ISegment, IUnleashConfig } from 'lib/types';
import { offlineUnleashClient } from './offline-unleash-client';
import { FeatureInterface } from 'lib/features/playground/feature-evaluator/feature';
import { FeatureStrategiesEvaluationResult } from 'lib/features/playground/feature-evaluator/client';
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 {
private readonly logger: Logger;
Expand All @@ -29,30 +38,38 @@ export class PlaygroundService {
this.segmentService = segmentService;
}

async evaluateQuery(
async evaluateAdvancedQuery(
projects: typeof ALL | string[],
environment: string,
environments: string[],
context: SdkContextSchema,
): Promise<PlaygroundFeatureSchema[]> {
const [features, segments] = await Promise.all([
this.featureToggleService.getClientFeatures(
{
project: projects === ALL ? undefined : projects,
environment,
},
true,
false,
const segments = await this.segmentService.getActive();
const environmentFeatures = await Promise.all(
environments.map((env) => this.resolveFeatures(projects, env)),
);
const contexts = generateObjectCombinations(context);

const results = await Promise.all(
environmentFeatures.flatMap(({ features, featureProject }) =>
contexts.map((singleContext) =>
this.evaluate({
features,
featureProject,
context: singleContext,
segments,
}),
),
),
this.segmentService.getActive(),
]);
const featureProject: Record<string, string> = features.reduce(
(obj, feature) => {
obj[feature.name] = feature.project;
return obj;
},
{},
);
return results.flat();
}

private async evaluate({
featureProject,
features,
segments,
context,
}: EvaluationInput): Promise<PlaygroundFeatureSchema[]> {
const [head, ...rest] = features;
if (!head) {
return [];
Expand Down Expand Up @@ -102,4 +119,39 @@ export class PlaygroundService {
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 });
}
}

0 comments on commit 7d69750

Please sign in to comment.