mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01: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