mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: dependent features use new transaction mechanism (#5073)
This commit is contained in:
		
							parent
							
								
									4dd01c1765
								
							
						
					
					
						commit
						75b131162e
					
				| @ -17,35 +17,33 @@ import { | ||||
| import { FeaturesReadModel } from '../feature-toggle/features-read-model'; | ||||
| import { FakeFeaturesReadModel } from '../feature-toggle/fakes/fake-features-read-model'; | ||||
| 
 | ||||
| export const createDependentFeaturesService = ( | ||||
|     db: Db, | ||||
|     config: IUnleashConfig, | ||||
| ): DependentFeaturesService => { | ||||
|     const { getLogger, eventBus } = config; | ||||
|     const eventStore = new EventStore(db, getLogger); | ||||
|     const featureTagStore = new FeatureTagStore(db, eventBus, getLogger); | ||||
|     const eventService = new EventService( | ||||
|         { | ||||
|             eventStore, | ||||
|             featureTagStore, | ||||
|         }, | ||||
|         config, | ||||
|     ); | ||||
|     const dependentFeaturesStore = new DependentFeaturesStore(db); | ||||
|     const dependentFeaturesReadModel = new DependentFeaturesReadModel(db); | ||||
|     const changeRequestAccessReadModel = createChangeRequestAccessReadModel( | ||||
|         db, | ||||
|         config, | ||||
|     ); | ||||
|     const featuresReadModel = new FeaturesReadModel(db); | ||||
|     return new DependentFeaturesService({ | ||||
|         dependentFeaturesStore, | ||||
|         dependentFeaturesReadModel, | ||||
|         changeRequestAccessReadModel, | ||||
|         featuresReadModel, | ||||
|         eventService, | ||||
|     }); | ||||
| }; | ||||
| export const createDependentFeaturesService = | ||||
|     (config: IUnleashConfig) => (db: Db): DependentFeaturesService => { | ||||
|         const { getLogger, eventBus } = config; | ||||
|         const eventStore = new EventStore(db, getLogger); | ||||
|         const featureTagStore = new FeatureTagStore(db, eventBus, getLogger); | ||||
|         const eventService = new EventService( | ||||
|             { | ||||
|                 eventStore, | ||||
|                 featureTagStore, | ||||
|             }, | ||||
|             config, | ||||
|         ); | ||||
|         const dependentFeaturesStore = new DependentFeaturesStore(db); | ||||
|         const dependentFeaturesReadModel = new DependentFeaturesReadModel(db); | ||||
|         const changeRequestAccessReadModel = createChangeRequestAccessReadModel( | ||||
|             db, | ||||
|             config, | ||||
|         ); | ||||
|         const featuresReadModel = new FeaturesReadModel(db); | ||||
|         return new DependentFeaturesService({ | ||||
|             dependentFeaturesStore, | ||||
|             dependentFeaturesReadModel, | ||||
|             changeRequestAccessReadModel, | ||||
|             featuresReadModel, | ||||
|             eventService, | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
| export const createFakeDependentFeaturesService = ( | ||||
|     config: IUnleashConfig, | ||||
|  | ||||
| @ -20,7 +20,11 @@ import { | ||||
| import { IAuthRequest } from '../../routes/unleash-types'; | ||||
| import { InvalidOperationError } from '../../error'; | ||||
| import { DependentFeaturesService } from './dependent-features-service'; | ||||
| import { TransactionCreator, UnleashTransaction } from '../../db/transaction'; | ||||
| import { | ||||
|     TransactionCreator, | ||||
|     UnleashTransaction, | ||||
|     WithTransactional, | ||||
| } from '../../db/transaction'; | ||||
| 
 | ||||
| interface ProjectParams { | ||||
|     projectId: string; | ||||
| @ -44,19 +48,11 @@ const PATH_DEPENDENCY = `${PATH_FEATURE}/dependencies/:parent`; | ||||
| 
 | ||||
| type DependentFeaturesServices = Pick< | ||||
|     IUnleashServices, | ||||
|     | 'transactionalDependentFeaturesService' | ||||
|     | 'dependentFeaturesService' | ||||
|     | 'openApiService' | ||||
|     'transactionalDependentFeaturesService' | 'openApiService' | ||||
| >; | ||||
| 
 | ||||
| export default class DependentFeaturesController extends Controller { | ||||
|     private transactionalDependentFeaturesService: ( | ||||
|         db: UnleashTransaction, | ||||
|     ) => DependentFeaturesService; | ||||
| 
 | ||||
|     private dependentFeaturesService: DependentFeaturesService; | ||||
| 
 | ||||
|     private readonly startTransaction: TransactionCreator<UnleashTransaction>; | ||||
|     private dependentFeaturesService: WithTransactional<DependentFeaturesService>; | ||||
| 
 | ||||
|     private openApiService: OpenApiService; | ||||
| 
 | ||||
| @ -68,18 +64,13 @@ export default class DependentFeaturesController extends Controller { | ||||
|         config: IUnleashConfig, | ||||
|         { | ||||
|             transactionalDependentFeaturesService, | ||||
|             dependentFeaturesService, | ||||
|             openApiService, | ||||
|         }: DependentFeaturesServices, | ||||
|         startTransaction: TransactionCreator<UnleashTransaction>, | ||||
|     ) { | ||||
|         super(config); | ||||
|         this.transactionalDependentFeaturesService = | ||||
|             transactionalDependentFeaturesService; | ||||
|         this.dependentFeaturesService = dependentFeaturesService; | ||||
|         this.dependentFeaturesService = transactionalDependentFeaturesService; | ||||
|         this.openApiService = openApiService; | ||||
|         this.flagResolver = config.flagResolver; | ||||
|         this.startTransaction = startTransaction; | ||||
|         this.logger = config.getLogger( | ||||
|             '/dependent-features/dependent-feature-service.ts', | ||||
|         ); | ||||
| @ -196,10 +187,8 @@ export default class DependentFeaturesController extends Controller { | ||||
|         const { variants, enabled, feature } = req.body; | ||||
| 
 | ||||
|         if (this.config.flagResolver.isEnabled('dependentFeatures')) { | ||||
|             await this.startTransaction(async (tx) => | ||||
|                 this.transactionalDependentFeaturesService( | ||||
|                     tx, | ||||
|                 ).upsertFeatureDependency( | ||||
|             await this.dependentFeaturesService.transactional((service) => | ||||
|                 service.upsertFeatureDependency( | ||||
|                     { child, projectId }, | ||||
|                     { | ||||
|                         variants, | ||||
| @ -209,6 +198,7 @@ export default class DependentFeaturesController extends Controller { | ||||
|                     req.user, | ||||
|                 ), | ||||
|             ); | ||||
| 
 | ||||
|             res.status(200).end(); | ||||
|         } else { | ||||
|             throw new InvalidOperationError( | ||||
| @ -224,13 +214,15 @@ export default class DependentFeaturesController extends Controller { | ||||
|         const { child, parent, projectId } = req.params; | ||||
| 
 | ||||
|         if (this.config.flagResolver.isEnabled('dependentFeatures')) { | ||||
|             await this.dependentFeaturesService.deleteFeatureDependency( | ||||
|                 { | ||||
|                     parent, | ||||
|                     child, | ||||
|                 }, | ||||
|                 projectId, | ||||
|                 req.user, | ||||
|             await this.dependentFeaturesService.transactional((service) => | ||||
|                 service.deleteFeatureDependency( | ||||
|                     { | ||||
|                         parent, | ||||
|                         child, | ||||
|                     }, | ||||
|                     projectId, | ||||
|                     req.user, | ||||
|                 ), | ||||
|             ); | ||||
|             res.status(200).end(); | ||||
|         } else { | ||||
| @ -247,10 +239,12 @@ export default class DependentFeaturesController extends Controller { | ||||
|         const { child, projectId } = req.params; | ||||
| 
 | ||||
|         if (this.config.flagResolver.isEnabled('dependentFeatures')) { | ||||
|             await this.dependentFeaturesService.deleteFeaturesDependencies( | ||||
|                 [child], | ||||
|                 projectId, | ||||
|                 req.user, | ||||
|             await this.dependentFeaturesService.transactional((service) => | ||||
|                 service.deleteFeaturesDependencies( | ||||
|                     [child], | ||||
|                     projectId, | ||||
|                     req.user, | ||||
|                 ), | ||||
|             ); | ||||
|             res.status(200).end(); | ||||
|         } else { | ||||
|  | ||||
| @ -236,10 +236,8 @@ export const deferredExportImportTogglesService = ( | ||||
| 
 | ||||
|         const segmentService = createSegmentService(db, config); | ||||
| 
 | ||||
|         const dependentFeaturesService = createDependentFeaturesService( | ||||
|             db, | ||||
|             config, | ||||
|         ); | ||||
|         const dependentFeaturesService = | ||||
|             createDependentFeaturesService(config)(db); | ||||
| 
 | ||||
|         const exportImportService = new ExportImportService( | ||||
|             { | ||||
|  | ||||
| @ -2,30 +2,29 @@ import { Logger } from '../../logger'; | ||||
| import { IStrategy } from '../../types/stores/strategy-store'; | ||||
| import { IFeatureToggleStore } from '../feature-toggle/types/feature-toggle-store-type'; | ||||
| import { IFeatureStrategiesStore } from '../feature-toggle/types/feature-toggle-strategies-store-type'; | ||||
| import { | ||||
|     IUnleashConfig, | ||||
|     IContextFieldStore, | ||||
|     IUnleashStores, | ||||
|     ISegmentStore, | ||||
|     IFeatureEnvironmentStore, | ||||
|     ITagTypeStore, | ||||
|     IFeatureTagStore, | ||||
|     FeatureToggleDTO, | ||||
|     IFeatureStrategy, | ||||
|     IFeatureStrategySegment, | ||||
|     IVariant, | ||||
| } from '../../types'; | ||||
| import { ExportQuerySchema, ImportTogglesSchema } from '../../openapi'; | ||||
| import { | ||||
|     FEATURES_EXPORTED, | ||||
|     FEATURES_IMPORTED, | ||||
|     FeatureToggleDTO, | ||||
|     IContextFieldStore, | ||||
|     IFeatureEnvironmentStore, | ||||
|     IFeatureStrategy, | ||||
|     IFeatureStrategySegment, | ||||
|     IFeatureTagStore, | ||||
|     IFlagResolver, | ||||
|     ISegmentStore, | ||||
|     ITagTypeStore, | ||||
|     IUnleashConfig, | ||||
|     IUnleashServices, | ||||
|     IUnleashStores, | ||||
|     IVariant, | ||||
|     WithRequired, | ||||
| } from '../../types'; | ||||
| import { | ||||
|     ExportQuerySchema, | ||||
|     ExportResultSchema, | ||||
|     FeatureStrategySchema, | ||||
|     ImportTogglesSchema, | ||||
|     ImportTogglesValidateSchema, | ||||
| } from '../../openapi'; | ||||
| import User from '../../types/user'; | ||||
|  | ||||
| @ -119,7 +119,7 @@ export const createFeatureToggleService = ( | ||||
| 
 | ||||
|     const dependentFeaturesReadModel = new DependentFeaturesReadModel(db); | ||||
| 
 | ||||
|     const dependentFeaturesService = createDependentFeaturesService(db, config); | ||||
|     const dependentFeaturesService = createDependentFeaturesService(config)(db); | ||||
| 
 | ||||
|     const featureToggleService = new FeatureToggleService( | ||||
|         { | ||||
|  | ||||
| @ -113,14 +113,7 @@ export default class ProjectApi extends Controller { | ||||
|                 createKnexTransactionStarter(db), | ||||
|             ).router, | ||||
|         ); | ||||
|         this.use( | ||||
|             '/', | ||||
|             new DependentFeaturesController( | ||||
|                 config, | ||||
|                 services, | ||||
|                 createKnexTransactionStarter(db), | ||||
|             ).router, | ||||
|         ); | ||||
|         this.use('/', new DependentFeaturesController(config, services).router); | ||||
|         this.use('/', new EnvironmentsController(config, services).router); | ||||
|         this.use('/', new ProjectHealthReport(config, services).router); | ||||
|         this.use('/', new VariantsController(config, services).router); | ||||
|  | ||||
| @ -267,11 +267,10 @@ export const createServices = ( | ||||
|         privateProjectChecker, | ||||
|     ); | ||||
| 
 | ||||
|     const dependentFeaturesService = db | ||||
|         ? createDependentFeaturesService(db, config) | ||||
|         : createFakeDependentFeaturesService(config); | ||||
|     const transactionalDependentFeaturesService = (txDb: Knex.Transaction) => | ||||
|         createDependentFeaturesService(txDb, config); | ||||
|     const transactionalDependentFeaturesService = db | ||||
|         ? withTransactional(createDependentFeaturesService(config), db) | ||||
|         : withFakeTransactional(createFakeDependentFeaturesService(config)); | ||||
|     const dependentFeaturesService = transactionalDependentFeaturesService; | ||||
| 
 | ||||
|     const featureToggleServiceV2 = new FeatureToggleService( | ||||
|         stores, | ||||
|  | ||||
| @ -105,8 +105,6 @@ export interface IUnleashServices { | ||||
|     transactionalGroupService: (db: Knex.Transaction) => GroupService; | ||||
|     privateProjectChecker: IPrivateProjectChecker; | ||||
|     dependentFeaturesService: DependentFeaturesService; | ||||
|     transactionalDependentFeaturesService: ( | ||||
|         db: Knex.Transaction, | ||||
|     ) => DependentFeaturesService; | ||||
|     transactionalDependentFeaturesService: WithTransactional<DependentFeaturesService>; | ||||
|     clientFeatureToggleService: ClientFeatureToggleService; | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user