diff --git a/src/lib/features/dependent-features/createDependentFeaturesService.ts b/src/lib/features/dependent-features/createDependentFeaturesService.ts index b317233a78..470a2bcad9 100644 --- a/src/lib/features/dependent-features/createDependentFeaturesService.ts +++ b/src/lib/features/dependent-features/createDependentFeaturesService.ts @@ -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, diff --git a/src/lib/features/dependent-features/dependent-features-controller.ts b/src/lib/features/dependent-features/dependent-features-controller.ts index 5923bcaeeb..8e56ceafe8 100644 --- a/src/lib/features/dependent-features/dependent-features-controller.ts +++ b/src/lib/features/dependent-features/dependent-features-controller.ts @@ -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; + private dependentFeaturesService: WithTransactional; private openApiService: OpenApiService; @@ -68,18 +64,13 @@ export default class DependentFeaturesController extends Controller { config: IUnleashConfig, { transactionalDependentFeaturesService, - dependentFeaturesService, openApiService, }: DependentFeaturesServices, - startTransaction: TransactionCreator, ) { 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 { diff --git a/src/lib/features/export-import-toggles/createExportImportService.ts b/src/lib/features/export-import-toggles/createExportImportService.ts index 01d6155f44..89e423b1b7 100644 --- a/src/lib/features/export-import-toggles/createExportImportService.ts +++ b/src/lib/features/export-import-toggles/createExportImportService.ts @@ -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( { diff --git a/src/lib/features/export-import-toggles/export-import-service.ts b/src/lib/features/export-import-toggles/export-import-service.ts index 9c1a92e2c4..b33346e1a9 100644 --- a/src/lib/features/export-import-toggles/export-import-service.ts +++ b/src/lib/features/export-import-toggles/export-import-service.ts @@ -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'; diff --git a/src/lib/features/feature-toggle/createFeatureToggleService.ts b/src/lib/features/feature-toggle/createFeatureToggleService.ts index 095ff22604..1860dc272c 100644 --- a/src/lib/features/feature-toggle/createFeatureToggleService.ts +++ b/src/lib/features/feature-toggle/createFeatureToggleService.ts @@ -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( { diff --git a/src/lib/routes/admin-api/project/index.ts b/src/lib/routes/admin-api/project/index.ts index d786a5fc8a..720c0e5634 100644 --- a/src/lib/routes/admin-api/project/index.ts +++ b/src/lib/routes/admin-api/project/index.ts @@ -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); diff --git a/src/lib/services/index.ts b/src/lib/services/index.ts index 2d91b96426..dbca8cd484 100644 --- a/src/lib/services/index.ts +++ b/src/lib/services/index.ts @@ -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, diff --git a/src/lib/types/services.ts b/src/lib/types/services.ts index 9aa05a8930..a226171984 100644 --- a/src/lib/types/services.ts +++ b/src/lib/types/services.ts @@ -105,8 +105,6 @@ export interface IUnleashServices { transactionalGroupService: (db: Knex.Transaction) => GroupService; privateProjectChecker: IPrivateProjectChecker; dependentFeaturesService: DependentFeaturesService; - transactionalDependentFeaturesService: ( - db: Knex.Transaction, - ) => DependentFeaturesService; + transactionalDependentFeaturesService: WithTransactional; clientFeatureToggleService: ClientFeatureToggleService; }