1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-19 01:17:18 +02:00

refactor: segment read model used in export-import (#6418)

This commit is contained in:
Mateusz Kwasniewski 2024-03-04 13:25:16 +01:00 committed by GitHub
parent 19fbd7a0c4
commit 14796aedc1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 110 additions and 33 deletions

View File

@ -25,12 +25,10 @@ import {
createFakeFeatureToggleService,
createFeatureToggleService,
} from '../feature-toggle/createFeatureToggleService';
import SegmentStore from '../../db/segment-store';
import { FeatureEnvironmentStore } from '../../db/feature-environment-store';
import FakeFeatureToggleStore from '../feature-toggle/fakes/fake-feature-toggle-store';
import FakeTagStore from '../../../test/fixtures/fake-tag-store';
import FakeTagTypeStore from '../tag-type/fake-tag-type-store';
import FakeSegmentStore from '../../../test/fixtures/fake-segment-store';
import FakeProjectStore from '../../../test/fixtures/fake-project-store';
import FakeFeatureTagStore from '../../../test/fixtures/fake-feature-tag-store';
import FakeContextFieldStore from '../../../test/fixtures/fake-context-field-store';
@ -46,15 +44,13 @@ import {
import { DeferredServiceFactory } from '../../db/transaction';
import { DependentFeaturesReadModel } from '../dependent-features/dependent-features-read-model';
import { FakeDependentFeaturesReadModel } from '../dependent-features/fake-dependent-features-read-model';
import {
createFakeSegmentService,
createSegmentService,
} from '../segment/createSegmentService';
import {
createDependentFeaturesService,
createFakeDependentFeaturesService,
} from '../dependent-features/createDependentFeaturesService';
import { createEventsService } from '../events/createEventsService';
import { SegmentReadModel } from '../segment/segment-read-model';
import { FakeSegmentReadModel } from '../segment/fake-segment-read-model';
export const createFakeExportImportTogglesService = (
config: IUnleashConfig,
@ -64,7 +60,6 @@ export const createFakeExportImportTogglesService = (
const featureToggleStore = new FakeFeatureToggleStore();
const tagStore = new FakeTagStore();
const tagTypeStore = new FakeTagTypeStore();
const segmentStore = new FakeSegmentStore();
const projectStore = new FakeProjectStore();
const featureTagStore = new FakeFeatureTagStore();
const strategyStore = new FakeStrategiesStore();
@ -115,7 +110,7 @@ export const createFakeExportImportTogglesService = (
);
const dependentFeaturesReadModel = new FakeDependentFeaturesReadModel();
const segmentService = createFakeSegmentService(config);
const segmentReadModel = new FakeSegmentReadModel();
const dependentFeaturesService = createFakeDependentFeaturesService(config);
@ -126,7 +121,6 @@ export const createFakeExportImportTogglesService = (
contextFieldStore,
featureToggleStore,
featureTagStore,
segmentStore,
tagTypeStore,
featureEnvironmentStore,
},
@ -139,10 +133,10 @@ export const createFakeExportImportTogglesService = (
contextService,
strategyService,
tagTypeService,
segmentService,
dependentFeaturesService,
},
dependentFeaturesReadModel,
segmentReadModel,
);
return exportImportService;
@ -162,12 +156,6 @@ export const deferredExportImportTogglesService = (
);
const tagStore = new TagStore(db, eventBus, getLogger);
const tagTypeStore = new TagTypeStore(db, eventBus, getLogger);
const segmentStore = new SegmentStore(
db,
eventBus,
getLogger,
flagResolver,
);
const projectStore = new ProjectStore(
db,
eventBus,
@ -230,7 +218,7 @@ export const deferredExportImportTogglesService = (
);
const dependentFeaturesReadModel = new DependentFeaturesReadModel(db);
const segmentService = createSegmentService(db, config);
const segmentReadModel = new SegmentReadModel(db);
const dependentFeaturesService =
createDependentFeaturesService(config)(db);
@ -242,7 +230,6 @@ export const deferredExportImportTogglesService = (
contextFieldStore,
featureToggleStore,
featureTagStore,
segmentStore,
tagTypeStore,
featureEnvironmentStore,
},
@ -255,10 +242,10 @@ export const deferredExportImportTogglesService = (
contextService,
strategyService,
tagTypeService,
segmentService,
dependentFeaturesService,
},
dependentFeaturesReadModel,
segmentReadModel,
);
return exportImportService;

View File

@ -12,7 +12,6 @@ import {
IFeatureStrategySegment,
IFeatureTagStore,
IFlagResolver,
ISegmentStore,
ITagTypeStore,
IUnleashConfig,
IUnleashServices,
@ -51,8 +50,8 @@ import { findDuplicates } from '../../util/findDuplicates';
import { FeatureNameCheckResultWithFeaturePattern } from '../feature-toggle/feature-toggle-service';
import { IDependentFeaturesReadModel } from '../dependent-features/dependent-features-read-model-type';
import groupBy from 'lodash.groupby';
import { ISegmentService } from '../../segments/segment-service-interface';
import { allSettledWithRejection } from '../../util/allSettledWithRejection';
import { ISegmentReadModel } from '../segment/segment-read-model-type';
export type IImportService = {
validate(
@ -88,8 +87,6 @@ export default class ExportImportService
private featureTagStore: IFeatureTagStore;
private segmentStore: ISegmentStore;
private flagResolver: IFlagResolver;
private featureToggleService: FeatureToggleService;
@ -106,7 +103,7 @@ export default class ExportImportService
private tagTypeService: TagTypeService;
private segmentService: ISegmentService;
private segmentReadModel: ISegmentReadModel;
private featureTagService: FeatureTagService;
@ -125,7 +122,6 @@ export default class ExportImportService
| 'featureEnvironmentStore'
| 'tagTypeStore'
| 'featureTagStore'
| 'segmentStore'
| 'contextFieldStore'
>,
{
@ -140,7 +136,6 @@ export default class ExportImportService
eventService,
tagTypeService,
featureTagService,
segmentService,
dependentFeaturesService,
}: Pick<
IUnleashServices,
@ -151,10 +146,10 @@ export default class ExportImportService
| 'eventService'
| 'tagTypeService'
| 'featureTagService'
| 'segmentService'
| 'dependentFeaturesService'
>,
dependentFeaturesReadModel: IDependentFeaturesReadModel,
segmentReadModel: ISegmentReadModel,
) {
this.toggleStore = stores.featureToggleStore;
this.importTogglesStore = stores.importTogglesStore;
@ -162,14 +157,12 @@ export default class ExportImportService
this.featureEnvironmentStore = stores.featureEnvironmentStore;
this.tagTypeStore = stores.tagTypeStore;
this.featureTagStore = stores.featureTagStore;
this.segmentStore = stores.segmentStore;
this.flagResolver = flagResolver;
this.featureToggleService = featureToggleService;
this.contextFieldStore = stores.contextFieldStore;
this.strategyService = strategyService;
this.contextService = contextService;
this.accessService = accessService;
this.segmentService = segmentService;
this.eventService = eventService;
this.tagTypeService = tagTypeService;
this.featureTagService = featureTagService;
@ -181,6 +174,7 @@ export default class ExportImportService
this.contextService,
);
this.dependentFeaturesReadModel = dependentFeaturesReadModel;
this.segmentReadModel = segmentReadModel;
this.logger = getLogger('services/state-service.js');
}
@ -479,7 +473,7 @@ export default class ExportImportService
private async getUnsupportedSegments(
dto: ImportTogglesSchema,
): Promise<string[]> {
const supportedSegments = await this.segmentService.getAll();
const supportedSegments = await this.segmentReadModel.getAll();
const targetProject = dto.project;
return dto.data.segments
? dto.data.segments
@ -583,7 +577,7 @@ export default class ExportImportService
}
private async remapSegments(dto: ImportTogglesSchema) {
const existingSegments = await this.segmentService.getAll();
const existingSegments = await this.segmentReadModel.getAll();
const segmentMapping = new Map(
dto.data.segments?.map((segment) => [
@ -820,10 +814,10 @@ export default class ExportImportService
featureNames,
query.environment,
),
this.segmentStore.getAllFeatureStrategySegments(),
this.segmentReadModel.getAllFeatureStrategySegments(),
this.contextFieldStore.getAll(),
this.featureTagStore.getAllByFeatures(featureNames),
this.segmentStore.getAll(),
this.segmentReadModel.getAll(),
this.tagTypeStore.getAll(),
this.dependentFeaturesReadModel.getDependencies(featureNames),
]);

View File

@ -0,0 +1,12 @@
import { IFeatureStrategySegment, ISegment } from '../../types';
import { ISegmentReadModel } from './segment-read-model-type';
export class FakeSegmentReadModel implements ISegmentReadModel {
async getAll(): Promise<ISegment[]> {
return [];
}
async getAllFeatureStrategySegments(): Promise<IFeatureStrategySegment[]> {
return [];
}
}

View File

@ -0,0 +1,6 @@
import { IFeatureStrategySegment, ISegment } from '../../types';
export interface ISegmentReadModel {
getAll(): Promise<ISegment[]>;
getAllFeatureStrategySegments(): Promise<IFeatureStrategySegment[]>;
}

View File

@ -0,0 +1,78 @@
import { IConstraint, IFeatureStrategySegment, ISegment } from '../../types';
import { ISegmentReadModel } from './segment-read-model-type';
import NotFoundError from '../../error/notfound-error';
import { Db } from '../../db/db';
interface ISegmentRow {
id: number;
name: string;
description?: string;
segment_project_id?: string;
created_by?: string;
created_at: Date;
constraints: IConstraint[];
}
const COLUMNS = [
'id',
'name',
'description',
'segment_project_id',
'created_by',
'created_at',
'constraints',
];
interface IFeatureStrategySegmentRow {
feature_strategy_id: string;
segment_id: number;
created_at?: Date;
}
export class SegmentReadModel implements ISegmentReadModel {
private db: Db;
constructor(db: Db) {
this.db = db;
}
prefixColumns(): string[] {
return COLUMNS.map((c) => `segments.${c}`);
}
mapRow(row?: ISegmentRow): ISegment {
if (!row) {
throw new NotFoundError('No row');
}
return {
id: row.id,
name: row.name,
description: row.description,
project: row.segment_project_id || undefined,
constraints: row.constraints,
createdBy: row.created_by,
createdAt: row.created_at,
};
}
async getAll(): Promise<ISegment[]> {
const rows: ISegmentRow[] = await this.db
.select(this.prefixColumns())
.from('segments')
.orderBy('segments.name', 'asc');
return rows.map(this.mapRow);
}
async getAllFeatureStrategySegments(): Promise<IFeatureStrategySegment[]> {
const rows: IFeatureStrategySegmentRow[] = await this.db
.select(['segment_id', 'feature_strategy_id'])
.from('feature_strategy_segment');
return rows.map((row) => ({
featureStrategyId: row.feature_strategy_id,
segmentId: row.segment_id,
}));
}
}