1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-07-21 13:47:39 +02:00

feat: transactional bulk update (#3806)

This commit is contained in:
Mateusz Kwasniewski 2023-05-19 08:44:17 +02:00 committed by GitHub
parent 4adc977ba0
commit f9409fc0e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 21 deletions

View File

@ -107,7 +107,7 @@ class AdminApi extends Controller {
'/feedback', '/feedback',
new UserFeedbackController(config, services).router, new UserFeedbackController(config, services).router,
); );
this.app.use('/projects', new ProjectApi(config, services).router); this.app.use('/projects', new ProjectApi(config, services, db).router);
this.app.use( this.app.use(
'/environments', '/environments',
new EnvironmentsController(config, services).router, new EnvironmentsController(config, services).router,

View File

@ -24,6 +24,8 @@ import { OpenApiService, SettingService } from '../../../services';
import { IAuthRequest } from '../../unleash-types'; import { IAuthRequest } from '../../unleash-types';
import { ProjectApiTokenController } from './api-token'; import { ProjectApiTokenController } from './api-token';
import ProjectArchiveController from './project-archive'; import ProjectArchiveController from './project-archive';
import { createKnexTransactionStarter } from '../../../db/transaction';
import { Db } from '../../../db/db';
export default class ProjectApi extends Controller { export default class ProjectApi extends Controller {
private projectService: ProjectService; private projectService: ProjectService;
@ -32,7 +34,7 @@ export default class ProjectApi extends Controller {
private openApiService: OpenApiService; private openApiService: OpenApiService;
constructor(config: IUnleashConfig, services: IUnleashServices) { constructor(config: IUnleashConfig, services: IUnleashServices, db: Db) {
super(config); super(config);
this.projectService = services.projectService; this.projectService = services.projectService;
this.openApiService = services.openApiService; this.openApiService = services.openApiService;
@ -70,7 +72,14 @@ export default class ProjectApi extends Controller {
], ],
}); });
this.use('/', new ProjectFeaturesController(config, services).router); this.use(
'/',
new ProjectFeaturesController(
config,
services,
createKnexTransactionStarter(db),
).router,
);
this.use('/', new EnvironmentsController(config, services).router); this.use('/', new EnvironmentsController(config, services).router);
this.use('/', new ProjectHealthReport(config, services).router); this.use('/', new ProjectHealthReport(config, services).router);
this.use('/', new VariantsController(config, services).router); this.use('/', new VariantsController(config, services).router);

View File

@ -42,6 +42,10 @@ import {
import { OpenApiService, FeatureToggleService } from '../../../services'; import { OpenApiService, FeatureToggleService } from '../../../services';
import { querySchema } from '../../../schema/feature-schema'; import { querySchema } from '../../../schema/feature-schema';
import { BatchStaleSchema } from '../../../openapi/spec/batch-stale-schema'; import { BatchStaleSchema } from '../../../openapi/spec/batch-stale-schema';
import {
TransactionCreator,
UnleashTransaction,
} from '../../../db/transaction';
interface FeatureStrategyParams { interface FeatureStrategyParams {
projectId: string; projectId: string;
@ -90,24 +94,41 @@ const PATH_STRATEGY = `${PATH_STRATEGIES}/:strategyId`;
type ProjectFeaturesServices = Pick< type ProjectFeaturesServices = Pick<
IUnleashServices, IUnleashServices,
'featureToggleServiceV2' | 'projectHealthService' | 'openApiService' | 'featureToggleServiceV2'
| 'projectHealthService'
| 'openApiService'
| 'transactionalFeatureToggleService'
>; >;
export default class ProjectFeaturesController extends Controller { export default class ProjectFeaturesController extends Controller {
private featureService: FeatureToggleService; private featureService: FeatureToggleService;
private transactionalFeatureToggleService: (
db: UnleashTransaction,
) => FeatureToggleService;
private openApiService: OpenApiService; private openApiService: OpenApiService;
private flagResolver: IFlagResolver; private flagResolver: IFlagResolver;
private readonly logger: Logger; private readonly logger: Logger;
private readonly startTransaction: TransactionCreator<UnleashTransaction>;
constructor( constructor(
config: IUnleashConfig, config: IUnleashConfig,
{ featureToggleServiceV2, openApiService }: ProjectFeaturesServices, {
featureToggleServiceV2,
openApiService,
transactionalFeatureToggleService,
}: ProjectFeaturesServices,
startTransaction: TransactionCreator<UnleashTransaction>,
) { ) {
super(config); super(config);
this.featureService = featureToggleServiceV2; this.featureService = featureToggleServiceV2;
this.transactionalFeatureToggleService =
transactionalFeatureToggleService;
this.startTransaction = startTransaction;
this.openApiService = openApiService; this.openApiService = openApiService;
this.flagResolver = config.flagResolver; this.flagResolver = config.flagResolver;
this.logger = config.getLogger('/admin-api/project/features.ts'); this.logger = config.getLogger('/admin-api/project/features.ts');
@ -727,14 +748,16 @@ export default class ProjectFeaturesController extends Controller {
const { shouldActivateDisabledStrategies } = req.query; const { shouldActivateDisabledStrategies } = req.query;
const { features } = req.body; const { features } = req.body;
await this.featureService.bulkUpdateEnabled( await this.startTransaction(async (tx) =>
projectId, this.transactionalFeatureToggleService(tx).bulkUpdateEnabled(
features, projectId,
environment, features,
true, environment,
extractUsername(req), true,
req.user, extractUsername(req),
shouldActivateDisabledStrategies === 'true', req.user,
shouldActivateDisabledStrategies === 'true',
),
); );
res.status(200).end(); res.status(200).end();
} }
@ -752,14 +775,16 @@ export default class ProjectFeaturesController extends Controller {
const { shouldActivateDisabledStrategies } = req.query; const { shouldActivateDisabledStrategies } = req.query;
const { features } = req.body; const { features } = req.body;
await this.featureService.bulkUpdateEnabled( await this.startTransaction(async (tx) =>
projectId, this.transactionalFeatureToggleService(tx).bulkUpdateEnabled(
features, projectId,
environment, features,
false, environment,
extractUsername(req), false,
req.user, extractUsername(req),
shouldActivateDisabledStrategies === 'true', req.user,
shouldActivateDisabledStrategies === 'true',
),
); );
res.status(200).end(); res.status(200).end();
} }

View File

@ -57,6 +57,7 @@ import {
createFakeChangeRequestAccessService, createFakeChangeRequestAccessService,
} from '../features/change-request-access-service/createChangeRequestAccessReadModel'; } from '../features/change-request-access-service/createChangeRequestAccessReadModel';
import ConfigurationRevisionService from '../features/feature-toggle/configuration-revision-service'; import ConfigurationRevisionService from '../features/feature-toggle/configuration-revision-service';
import { createFeatureToggleService } from '../features';
// TODO: will be moved to scheduler feature directory // TODO: will be moved to scheduler feature directory
export const scheduleServices = (services: IUnleashServices): void => { export const scheduleServices = (services: IUnleashServices): void => {
@ -184,6 +185,8 @@ export const createServices = (
: createFakeExportImportTogglesService(config); : createFakeExportImportTogglesService(config);
const transactionalExportImportService = (txDb: Knex.Transaction) => const transactionalExportImportService = (txDb: Knex.Transaction) =>
createExportImportTogglesService(txDb, config); createExportImportTogglesService(txDb, config);
const transactionalFeatureToggleService = (txDb: Knex.Transaction) =>
createFeatureToggleService(txDb, config);
const userSplashService = new UserSplashService(stores, config); const userSplashService = new UserSplashService(stores, config);
const openApiService = new OpenApiService(config); const openApiService = new OpenApiService(config);
const clientSpecService = new ClientSpecService(config); const clientSpecService = new ClientSpecService(config);
@ -275,6 +278,7 @@ export const createServices = (
transactionalExportImportService, transactionalExportImportService,
schedulerService, schedulerService,
configurationRevisionService, configurationRevisionService,
transactionalFeatureToggleService,
}; };
}; };

View File

@ -91,4 +91,7 @@ export interface IUnleashServices {
transactionalExportImportService: ( transactionalExportImportService: (
db: Knex.Transaction, db: Knex.Transaction,
) => ExportImportService; ) => ExportImportService;
transactionalFeatureToggleService: (
db: Knex.Transaction,
) => FeatureToggleService;
} }