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:
parent
19fbd7a0c4
commit
14796aedc1
@ -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;
|
||||
|
@ -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),
|
||||
]);
|
||||
|
12
src/lib/features/segment/fake-segment-read-model.ts
Normal file
12
src/lib/features/segment/fake-segment-read-model.ts
Normal 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 [];
|
||||
}
|
||||
}
|
6
src/lib/features/segment/segment-read-model-type.ts
Normal file
6
src/lib/features/segment/segment-read-model-type.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { IFeatureStrategySegment, ISegment } from '../../types';
|
||||
|
||||
export interface ISegmentReadModel {
|
||||
getAll(): Promise<ISegment[]>;
|
||||
getAllFeatureStrategySegments(): Promise<IFeatureStrategySegment[]>;
|
||||
}
|
78
src/lib/features/segment/segment-read-model.ts
Normal file
78
src/lib/features/segment/segment-read-model.ts
Normal 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,
|
||||
}));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user