Skip to content

Commit

Permalink
refactor: segment read model used in export-import (#6418)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwasniew authored Mar 4, 2024
1 parent 19fbd7a commit 14796ae
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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,
Expand All @@ -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();
Expand Down Expand Up @@ -115,7 +110,7 @@ export const createFakeExportImportTogglesService = (
);
const dependentFeaturesReadModel = new FakeDependentFeaturesReadModel();

const segmentService = createFakeSegmentService(config);
const segmentReadModel = new FakeSegmentReadModel();

const dependentFeaturesService = createFakeDependentFeaturesService(config);

Expand All @@ -126,7 +121,6 @@ export const createFakeExportImportTogglesService = (
contextFieldStore,
featureToggleStore,
featureTagStore,
segmentStore,
tagTypeStore,
featureEnvironmentStore,
},
Expand All @@ -139,10 +133,10 @@ export const createFakeExportImportTogglesService = (
contextService,
strategyService,
tagTypeService,
segmentService,
dependentFeaturesService,
},
dependentFeaturesReadModel,
segmentReadModel,
);

return exportImportService;
Expand All @@ -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,
Expand Down Expand Up @@ -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);
Expand All @@ -242,7 +230,6 @@ export const deferredExportImportTogglesService = (
contextFieldStore,
featureToggleStore,
featureTagStore,
segmentStore,
tagTypeStore,
featureEnvironmentStore,
},
Expand All @@ -255,10 +242,10 @@ export const deferredExportImportTogglesService = (
contextService,
strategyService,
tagTypeService,
segmentService,
dependentFeaturesService,
},
dependentFeaturesReadModel,
segmentReadModel,
);

return exportImportService;
Expand Down
22 changes: 8 additions & 14 deletions src/lib/features/export-import-toggles/export-import-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
IFeatureStrategySegment,
IFeatureTagStore,
IFlagResolver,
ISegmentStore,
ITagTypeStore,
IUnleashConfig,
IUnleashServices,
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -88,8 +87,6 @@ export default class ExportImportService

private featureTagStore: IFeatureTagStore;

private segmentStore: ISegmentStore;

private flagResolver: IFlagResolver;

private featureToggleService: FeatureToggleService;
Expand All @@ -106,7 +103,7 @@ export default class ExportImportService

private tagTypeService: TagTypeService;

private segmentService: ISegmentService;
private segmentReadModel: ISegmentReadModel;

private featureTagService: FeatureTagService;

Expand All @@ -125,7 +122,6 @@ export default class ExportImportService
| 'featureEnvironmentStore'
| 'tagTypeStore'
| 'featureTagStore'
| 'segmentStore'
| 'contextFieldStore'
>,
{
Expand All @@ -140,7 +136,6 @@ export default class ExportImportService
eventService,
tagTypeService,
featureTagService,
segmentService,
dependentFeaturesService,
}: Pick<
IUnleashServices,
Expand All @@ -151,25 +146,23 @@ export default class ExportImportService
| 'eventService'
| 'tagTypeService'
| 'featureTagService'
| 'segmentService'
| 'dependentFeaturesService'
>,
dependentFeaturesReadModel: IDependentFeaturesReadModel,
segmentReadModel: ISegmentReadModel,
) {
this.toggleStore = stores.featureToggleStore;
this.importTogglesStore = stores.importTogglesStore;
this.featureStrategiesStore = stores.featureStrategiesStore;
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;
Expand All @@ -181,6 +174,7 @@ export default class ExportImportService
this.contextService,
);
this.dependentFeaturesReadModel = dependentFeaturesReadModel;
this.segmentReadModel = segmentReadModel;
this.logger = getLogger('services/state-service.js');
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) => [
Expand Down Expand Up @@ -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),
]);
Expand Down
12 changes: 12 additions & 0 deletions src/lib/features/segment/fake-segment-read-model.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 6 additions & 0 deletions src/lib/features/segment/segment-read-model-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { IFeatureStrategySegment, ISegment } from '../../types';

export interface ISegmentReadModel {
getAll(): Promise<ISegment[]>;
getAllFeatureStrategySegments(): Promise<IFeatureStrategySegment[]>;
}
78 changes: 78 additions & 0 deletions src/lib/features/segment/segment-read-model.ts
Original file line number Diff line number Diff line change
@@ -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,
}));
}
}

0 comments on commit 14796ae

Please sign in to comment.