From 26f9cf98d575d5f014cb7d97d9bbfae1561d618e Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Fri, 1 Dec 2023 12:41:46 +0100 Subject: [PATCH] refactor: feature oriented architecture for project-environment (#5510) --- src/lib/db/index.ts | 2 +- .../features/access/createAccessService.ts | 4 +- .../createFeatureToggleService.ts | 4 +- .../tests/feature-toggle-service.e2e.test.ts | 2 +- src/lib/features/index.ts | 1 + .../instance-stats/instance-stats-service.ts | 2 +- .../createEnvironmentService.ts | 88 +++++++++++++++++++ .../environment-service.test.ts | 14 +-- .../environment-service.ts | 18 ++-- .../environment-store-type.ts} | 4 +- .../environment-store.ts | 18 ++-- .../environments.e2e.test.ts | 8 +- .../project-environments}/environments.ts | 59 +++++++------ .../fake-environment-store.ts | 6 +- .../features/project/createProjectService.ts | 4 +- src/lib/routes/admin-api/environments.ts | 2 +- .../routes/admin-api/project/project-api.ts | 2 +- src/lib/services/access-service.test.ts | 2 +- src/lib/services/access-service.ts | 6 +- src/lib/services/api-token-service.test.ts | 2 +- src/lib/services/api-token-service.ts | 2 +- src/lib/services/index.ts | 15 ++-- src/lib/services/state-service.ts | 2 +- src/lib/types/services.ts | 3 +- src/lib/types/stores.ts | 2 +- src/test/e2e/api/admin/environment.test.ts | 14 +-- src/test/e2e/api/admin/state.e2e.test.ts | 18 +++- src/test/e2e/helpers/database-init.ts | 2 +- .../e2e/services/project-service.e2e.test.ts | 2 +- .../feature-environment-store.e2e.test.ts | 2 +- src/test/e2e/stores/project-store.e2e.test.ts | 2 +- src/test/fixtures/store.ts | 2 +- 32 files changed, 217 insertions(+), 97 deletions(-) create mode 100644 src/lib/features/project-environments/createEnvironmentService.ts rename src/{test/e2e/services => lib/features/project-environments}/environment-service.test.ts (95%) rename src/lib/{services => features/project-environments}/environment-service.ts (94%) rename src/lib/{types/stores/environment-store.ts => features/project-environments/environment-store-type.ts} (93%) rename src/lib/{db => features/project-environments}/environment-store.ts (95%) rename src/{test/e2e/api/admin/project => lib/features/project-environments}/environments.e2e.test.ts (95%) rename src/lib/{routes/admin-api/project => features/project-environments}/environments.ts (78%) rename src/{test/fixtures => lib/features/project-environments}/fake-environment-store.ts (95%) diff --git a/src/lib/db/index.ts b/src/lib/db/index.ts index 24d7ca757bbe..48209cb6487d 100644 --- a/src/lib/db/index.ts +++ b/src/lib/db/index.ts @@ -20,7 +20,7 @@ import { ResetTokenStore } from './reset-token-store'; import UserFeedbackStore from './user-feedback-store'; import FeatureStrategyStore from '../features/feature-toggle/feature-toggle-strategies-store'; import FeatureToggleClientStore from '../features/client-feature-toggles/client-feature-toggle-store'; -import EnvironmentStore from './environment-store'; +import EnvironmentStore from '../features/project-environments/environment-store'; import FeatureTagStore from './feature-tag-store'; import { FeatureEnvironmentStore } from './feature-environment-store'; import { ClientMetricsStoreV2 } from './client-metrics-store-v2'; diff --git a/src/lib/features/access/createAccessService.ts b/src/lib/features/access/createAccessService.ts index 19ce933c21c0..673fb1b43958 100644 --- a/src/lib/features/access/createAccessService.ts +++ b/src/lib/features/access/createAccessService.ts @@ -3,14 +3,14 @@ import EventStore from '../../db/event-store'; import GroupStore from '../../db/group-store'; import { AccountStore } from '../../db/account-store'; import RoleStore from '../../db/role-store'; -import EnvironmentStore from '../../db/environment-store'; +import EnvironmentStore from '../project-environments/environment-store'; import { AccessStore } from '../../db/access-store'; import { AccessService, EventService, GroupService } from '../../services'; import FakeGroupStore from '../../../test/fixtures/fake-group-store'; import FakeEventStore from '../../../test/fixtures/fake-event-store'; import { FakeAccountStore } from '../../../test/fixtures/fake-account-store'; import FakeRoleStore from '../../../test/fixtures/fake-role-store'; -import FakeEnvironmentStore from '../../../test/fixtures/fake-environment-store'; +import FakeEnvironmentStore from '../project-environments/fake-environment-store'; import FakeAccessStore from '../../../test/fixtures/fake-access-store'; import FeatureTagStore from '../../db/feature-tag-store'; import FakeFeatureTagStore from '../../../test/fixtures/fake-feature-tag-store'; diff --git a/src/lib/features/feature-toggle/createFeatureToggleService.ts b/src/lib/features/feature-toggle/createFeatureToggleService.ts index a56fb68c4841..53be306b9ec2 100644 --- a/src/lib/features/feature-toggle/createFeatureToggleService.ts +++ b/src/lib/features/feature-toggle/createFeatureToggleService.ts @@ -14,7 +14,7 @@ import GroupStore from '../../db/group-store'; import { AccountStore } from '../../db/account-store'; import { AccessStore } from '../../db/access-store'; import RoleStore from '../../db/role-store'; -import EnvironmentStore from '../../db/environment-store'; +import EnvironmentStore from '../project-environments/environment-store'; import { Db } from '../../db/db'; import { IUnleashConfig } from '../../types'; import FakeEventStore from '../../../test/fixtures/fake-event-store'; @@ -28,7 +28,7 @@ import FakeGroupStore from '../../../test/fixtures/fake-group-store'; import { FakeAccountStore } from '../../../test/fixtures/fake-account-store'; import FakeAccessStore from '../../../test/fixtures/fake-access-store'; import FakeRoleStore from '../../../test/fixtures/fake-role-store'; -import FakeEnvironmentStore from '../../../test/fixtures/fake-environment-store'; +import FakeEnvironmentStore from '../project-environments/fake-environment-store'; import EventStore from '../../db/event-store'; import { createChangeRequestAccessReadModel, diff --git a/src/lib/features/feature-toggle/tests/feature-toggle-service.e2e.test.ts b/src/lib/features/feature-toggle/tests/feature-toggle-service.e2e.test.ts index 7aa7e8e8ec91..9864394efefe 100644 --- a/src/lib/features/feature-toggle/tests/feature-toggle-service.e2e.test.ts +++ b/src/lib/features/feature-toggle/tests/feature-toggle-service.e2e.test.ts @@ -10,7 +10,7 @@ import { IVariant, SKIP_CHANGE_REQUEST, } from '../../../types'; -import EnvironmentService from '../../../services/environment-service'; +import EnvironmentService from '../../project-environments/environment-service'; import { ForbiddenError, PatternError, PermissionError } from '../../../error'; import { ISegmentService } from '../../../segments/segment-service-interface'; import { createFeatureToggleService, createSegmentService } from '../..'; diff --git a/src/lib/features/index.ts b/src/lib/features/index.ts index 1b008b0da4a5..028353bd4663 100644 --- a/src/lib/features/index.ts +++ b/src/lib/features/index.ts @@ -6,3 +6,4 @@ export * from './change-request-access-service/createChangeRequestAccessReadMode export * from './segment/createSegmentService'; export * from './dependent-features/createDependentFeaturesService'; export * from './tag-type/createTagTypeService'; +export * from './project-environments/createEnvironmentService'; diff --git a/src/lib/features/instance-stats/instance-stats-service.ts b/src/lib/features/instance-stats/instance-stats-service.ts index 2154f7e99b4e..ea94956989ba 100644 --- a/src/lib/features/instance-stats/instance-stats-service.ts +++ b/src/lib/features/instance-stats/instance-stats-service.ts @@ -7,7 +7,7 @@ import { IUnleashStores, } from '../../types/stores'; import { IContextFieldStore } from '../../types/stores/context-field-store'; -import { IEnvironmentStore } from '../../types/stores/environment-store'; +import { IEnvironmentStore } from '../project-environments/environment-store-type'; import { IFeatureToggleStore } from '../feature-toggle/types/feature-toggle-store-type'; import { IGroupStore } from '../../types/stores/group-store'; import { IProjectStore } from '../../types/stores/project-store'; diff --git a/src/lib/features/project-environments/createEnvironmentService.ts b/src/lib/features/project-environments/createEnvironmentService.ts new file mode 100644 index 000000000000..d8b4ef6d7404 --- /dev/null +++ b/src/lib/features/project-environments/createEnvironmentService.ts @@ -0,0 +1,88 @@ +import { Db } from '../../db/db'; +import EventStore from '../../db/event-store'; +import { IUnleashConfig } from '../../types'; +import { EventService } from '../../services'; +import FeatureTagStore from '../../db/feature-tag-store'; +import FakeEventStore from '../../../test/fixtures/fake-event-store'; +import FakeFeatureTagStore from '../../../test/fixtures/fake-feature-tag-store'; +import EnvironmentService from './environment-service'; +import EnvironmentStore from './environment-store'; +import FeatureStrategiesStore from '../feature-toggle/feature-toggle-strategies-store'; +import { FeatureEnvironmentStore } from '../../db/feature-environment-store'; +import ProjectStore from '../../db/project-store'; +import FakeFeatureEnvironmentStore from '../../../test/fixtures/fake-feature-environment-store'; +import FakeProjectStore from '../../../test/fixtures/fake-project-store'; +import FakeFeatureStrategiesStore from '../feature-toggle/fakes/fake-feature-strategies-store'; +import FakeEnvironmentStore from './fake-environment-store'; + +export const createEnvironmentService = + (config: IUnleashConfig) => + (db: Db): EnvironmentService => { + const { getLogger, eventBus, flagResolver } = config; + const eventStore = new EventStore(db, getLogger); + const featureTagStore = new FeatureTagStore(db, eventBus, getLogger); + const featureEnvironmentStore = new FeatureEnvironmentStore( + db, + eventBus, + getLogger, + ); + const projectStore = new ProjectStore( + db, + eventBus, + getLogger, + flagResolver, + ); + const featureStrategiesStore = new FeatureStrategiesStore( + db, + eventBus, + getLogger, + flagResolver, + ); + const environmentStore = new EnvironmentStore(db, eventBus, getLogger); + const eventService = new EventService( + { + eventStore, + featureTagStore, + }, + config, + ); + return new EnvironmentService( + { + environmentStore, + featureStrategiesStore, + featureEnvironmentStore, + projectStore, + }, + config, + eventService, + ); + }; + +export const createFakeEnvironmentService = ( + config: IUnleashConfig, +): EnvironmentService => { + const eventStore = new FakeEventStore(); + const featureTagStore = new FakeFeatureTagStore(); + const featureEnvironmentStore = new FakeFeatureEnvironmentStore(); + const projectStore = new FakeProjectStore(); + const featureStrategiesStore = new FakeFeatureStrategiesStore(); + const environmentStore = new FakeEnvironmentStore(); + const eventService = new EventService( + { + eventStore, + featureTagStore, + }, + config, + ); + + return new EnvironmentService( + { + environmentStore, + featureStrategiesStore, + featureEnvironmentStore, + projectStore, + }, + config, + eventService, + ); +}; diff --git a/src/test/e2e/services/environment-service.test.ts b/src/lib/features/project-environments/environment-service.test.ts similarity index 95% rename from src/test/e2e/services/environment-service.test.ts rename to src/lib/features/project-environments/environment-service.test.ts index b214f3cfb5a7..4f92cd509ffb 100644 --- a/src/test/e2e/services/environment-service.test.ts +++ b/src/lib/features/project-environments/environment-service.test.ts @@ -1,10 +1,10 @@ -import EnvironmentService from '../../../lib/services/environment-service'; -import { createTestConfig } from '../../config/test-config'; -import dbInit from '../helpers/database-init'; -import NotFoundError from '../../../lib/error/notfound-error'; -import { IUnleashStores } from '../../../lib/types'; -import NameExistsError from '../../../lib/error/name-exists-error'; -import { EventService } from '../../../lib/services'; +import EnvironmentService from './environment-service'; +import { createTestConfig } from '../../../test/config/test-config'; +import dbInit from '../../../test/e2e/helpers/database-init'; +import NotFoundError from '../../error/notfound-error'; +import { IUnleashStores } from '../../types'; +import NameExistsError from '../../error/name-exists-error'; +import { EventService } from '../../services'; let stores: IUnleashStores; let db; diff --git a/src/lib/services/environment-service.ts b/src/lib/features/project-environments/environment-service.ts similarity index 94% rename from src/lib/services/environment-service.ts rename to src/lib/features/project-environments/environment-service.ts index 6eef9349ab71..311df68e60df 100644 --- a/src/lib/services/environment-service.ts +++ b/src/lib/features/project-environments/environment-service.ts @@ -10,17 +10,17 @@ import { IUnleashStores, PROJECT_ENVIRONMENT_ADDED, PROJECT_ENVIRONMENT_REMOVED, -} from '../types'; -import { Logger } from '../logger'; -import { BadDataError, UNIQUE_CONSTRAINT_VIOLATION } from '../error'; -import NameExistsError from '../error/name-exists-error'; -import { sortOrderSchema } from './state-schema'; -import NotFoundError from '../error/notfound-error'; +} from '../../types'; +import { Logger } from '../../logger'; +import { BadDataError, UNIQUE_CONSTRAINT_VIOLATION } from '../../error'; +import NameExistsError from '../../error/name-exists-error'; +import { sortOrderSchema } from '../../services/state-schema'; +import NotFoundError from '../../error/notfound-error'; import { IProjectStore } from 'lib/types/stores/project-store'; -import MinimumOneEnvironmentError from '../error/minimum-one-environment-error'; +import MinimumOneEnvironmentError from '../../error/minimum-one-environment-error'; import { IFlagResolver } from 'lib/types/experimental'; -import { CreateFeatureStrategySchema } from '../openapi'; -import EventService from './event-service'; +import { CreateFeatureStrategySchema } from '../../openapi'; +import EventService from '../../services/event-service'; export default class EnvironmentService { private logger: Logger; diff --git a/src/lib/types/stores/environment-store.ts b/src/lib/features/project-environments/environment-store-type.ts similarity index 93% rename from src/lib/types/stores/environment-store.ts rename to src/lib/features/project-environments/environment-store-type.ts index d56ad4a4a324..5926b76f0fe7 100644 --- a/src/lib/types/stores/environment-store.ts +++ b/src/lib/features/project-environments/environment-store-type.ts @@ -2,8 +2,8 @@ import { IEnvironment, IEnvironmentCreate, IProjectEnvironment, -} from '../model'; -import { Store } from './store'; +} from '../../types/model'; +import { Store } from '../../types/stores/store'; export interface IEnvironmentStore extends Store { exists(name: string): Promise; diff --git a/src/lib/db/environment-store.ts b/src/lib/features/project-environments/environment-store.ts similarity index 95% rename from src/lib/db/environment-store.ts rename to src/lib/features/project-environments/environment-store.ts index 605760af9b19..b74a91cf04f5 100644 --- a/src/lib/db/environment-store.ts +++ b/src/lib/features/project-environments/environment-store.ts @@ -1,17 +1,17 @@ import EventEmitter from 'events'; -import { Db } from './db'; -import { Logger, LogProvider } from '../logger'; -import metricsHelper from '../util/metrics-helper'; -import { DB_TIME } from '../metric-events'; +import { Db } from '../../db/db'; +import { Logger, LogProvider } from '../../logger'; +import metricsHelper from '../../util/metrics-helper'; +import { DB_TIME } from '../../metric-events'; import { IEnvironment, IEnvironmentCreate, IProjectEnvironment, -} from '../types/model'; -import NotFoundError from '../error/notfound-error'; -import { IEnvironmentStore } from '../types/stores/environment-store'; -import { snakeCaseKeys } from '../util/snakeCase'; -import { CreateFeatureStrategySchema } from '../openapi'; +} from '../../types/model'; +import NotFoundError from '../../error/notfound-error'; +import { IEnvironmentStore } from './environment-store-type'; +import { snakeCaseKeys } from '../../util/snakeCase'; +import { CreateFeatureStrategySchema } from '../../openapi'; interface IEnvironmentsTable { name: string; diff --git a/src/test/e2e/api/admin/project/environments.e2e.test.ts b/src/lib/features/project-environments/environments.e2e.test.ts similarity index 95% rename from src/test/e2e/api/admin/project/environments.e2e.test.ts rename to src/lib/features/project-environments/environments.e2e.test.ts index 5d2b2cd43d5e..417fa73642c0 100644 --- a/src/test/e2e/api/admin/project/environments.e2e.test.ts +++ b/src/lib/features/project-environments/environments.e2e.test.ts @@ -1,10 +1,10 @@ -import dbInit, { ITestDb } from '../../../helpers/database-init'; +import dbInit, { ITestDb } from '../../../test/e2e/helpers/database-init'; import { IUnleashTest, setupAppWithCustomConfig, -} from '../../../helpers/test-helper'; -import getLogger from '../../../../fixtures/no-logger'; -import { DEFAULT_ENV } from '../../../../../lib/util'; +} from '../../../test/e2e/helpers/test-helper'; +import getLogger from '../../../test/fixtures/no-logger'; +import { DEFAULT_ENV } from '../../util'; let app: IUnleashTest; let db: ITestDb; diff --git a/src/lib/routes/admin-api/project/environments.ts b/src/lib/features/project-environments/environments.ts similarity index 78% rename from src/lib/routes/admin-api/project/environments.ts rename to src/lib/features/project-environments/environments.ts index 044f15555272..7a875e3d5e17 100644 --- a/src/lib/routes/admin-api/project/environments.ts +++ b/src/lib/features/project-environments/environments.ts @@ -1,13 +1,13 @@ import { Request, Response } from 'express'; -import Controller from '../../controller'; +import Controller from '../../routes/controller'; import { IUnleashConfig, IUnleashServices, serializeDates, UPDATE_PROJECT, -} from '../../../types'; -import { Logger } from '../../../logger'; -import EnvironmentService from '../../../services/environment-service'; +} from '../../types'; +import { Logger } from '../../logger'; +import EnvironmentService from './environment-service'; import { createFeatureStrategySchema, CreateFeatureStrategySchema, @@ -16,10 +16,11 @@ import { emptyResponse, getStandardResponses, ProjectEnvironmentSchema, -} from '../../../openapi'; -import { OpenApiService, ProjectService } from '../../../services'; -import { extractUsername } from '../../../util'; -import { IAuthRequest } from '../../unleash-types'; +} from '../../openapi'; +import { OpenApiService, ProjectService } from '../../services'; +import { extractUsername } from '../../util'; +import { IAuthRequest } from '../../routes/unleash-types'; +import { WithTransactional } from '../../db/transaction'; const PREFIX = '/:projectId/environments'; @@ -31,7 +32,7 @@ interface IProjectEnvironmentParams { export default class EnvironmentsController extends Controller { private logger: Logger; - private environmentService: EnvironmentService; + private environmentService: WithTransactional; private openApiService: OpenApiService; @@ -40,18 +41,20 @@ export default class EnvironmentsController extends Controller { constructor( config: IUnleashConfig, { - environmentService, + transactionalEnvironmentService, openApiService, projectService, }: Pick< IUnleashServices, - 'environmentService' | 'openApiService' | 'projectService' + | 'transactionalEnvironmentService' + | 'openApiService' + | 'projectService' >, ) { super(config); this.logger = config.getLogger('admin-api/project/environments.ts'); - this.environmentService = environmentService; + this.environmentService = transactionalEnvironmentService; this.openApiService = openApiService; this.projectService = projectService; @@ -137,10 +140,12 @@ export default class EnvironmentsController extends Controller { const { environment } = req.body; await this.projectService.getProject(projectId); // Validates that the project exists - await this.environmentService.addEnvironmentToProject( - environment, - projectId, - extractUsername(req), + await this.environmentService.transactional((service) => + service.addEnvironmentToProject( + environment, + projectId, + extractUsername(req), + ), ); res.status(200).end(); @@ -152,10 +157,12 @@ export default class EnvironmentsController extends Controller { ): Promise { const { projectId, environment } = req.params; - await this.environmentService.removeEnvironmentFromProject( - environment, - projectId, - extractUsername(req), + await this.environmentService.transactional((service) => + service.removeEnvironmentFromProject( + environment, + projectId, + extractUsername(req), + ), ); res.status(200).end(); @@ -171,11 +178,13 @@ export default class EnvironmentsController extends Controller { const { projectId, environment } = req.params; const strategy = req.body; - const saved = await this.environmentService.updateDefaultStrategy( - environment, - projectId, - strategy, - extractUsername(req), + const saved = await this.environmentService.transactional((service) => + service.updateDefaultStrategy( + environment, + projectId, + strategy, + extractUsername(req), + ), ); this.openApiService.respondWithValidation( diff --git a/src/test/fixtures/fake-environment-store.ts b/src/lib/features/project-environments/fake-environment-store.ts similarity index 95% rename from src/test/fixtures/fake-environment-store.ts rename to src/lib/features/project-environments/fake-environment-store.ts index 775939fa37f4..b6af7c706fca 100644 --- a/src/test/fixtures/fake-environment-store.ts +++ b/src/lib/features/project-environments/fake-environment-store.ts @@ -1,6 +1,6 @@ -import { IEnvironment, IProjectEnvironment } from '../../lib/types/model'; -import NotFoundError from '../../lib/error/notfound-error'; -import { IEnvironmentStore } from '../../lib/types/stores/environment-store'; +import { IEnvironment, IProjectEnvironment } from '../../types/model'; +import NotFoundError from '../../error/notfound-error'; +import { IEnvironmentStore } from './environment-store-type'; export default class FakeEnvironmentStore implements IEnvironmentStore { importEnvironments(envs: IEnvironment[]): Promise { diff --git a/src/lib/features/project/createProjectService.ts b/src/lib/features/project/createProjectService.ts index e9c14841cd89..9bf31d7eaebd 100644 --- a/src/lib/features/project/createProjectService.ts +++ b/src/lib/features/project/createProjectService.ts @@ -2,7 +2,7 @@ import { Db, IUnleashConfig } from 'lib/server-impl'; import EventStore from '../../db/event-store'; import GroupStore from '../../db/group-store'; import { AccountStore } from '../../db/account-store'; -import EnvironmentStore from '../../db/environment-store'; +import EnvironmentStore from '../project-environments/environment-store'; import { AccessService, EventService, @@ -28,7 +28,7 @@ import { FavoriteFeaturesStore } from '../../db/favorite-features-store'; import { FavoriteProjectsStore } from '../../db/favorite-projects-store'; import FakeProjectStore from '../../../test/fixtures/fake-project-store'; import FakeFeatureToggleStore from '../feature-toggle/fakes/fake-feature-toggle-store'; -import FakeEnvironmentStore from '../../../test/fixtures/fake-environment-store'; +import FakeEnvironmentStore from '../project-environments/fake-environment-store'; import FakeFeatureEnvironmentStore from '../../../test/fixtures/fake-feature-environment-store'; import FakeProjectStatsStore from '../../../test/fixtures/fake-project-stats-store'; import FakeFavoriteFeaturesStore from '../../../test/fixtures/fake-favorite-features-store'; diff --git a/src/lib/routes/admin-api/environments.ts b/src/lib/routes/admin-api/environments.ts index 8928abbdd537..adcf3f0b0e9f 100644 --- a/src/lib/routes/admin-api/environments.ts +++ b/src/lib/routes/admin-api/environments.ts @@ -2,7 +2,7 @@ import { Request, Response } from 'express'; import Controller from '../controller'; import { IUnleashServices } from '../../types/services'; import { IUnleashConfig } from '../../types/option'; -import EnvironmentService from '../../services/environment-service'; +import EnvironmentService from '../../features/project-environments/environment-service'; import { Logger } from '../../logger'; import { ADMIN, NONE } from '../../types/permissions'; import { OpenApiService } from '../../services/openapi-service'; diff --git a/src/lib/routes/admin-api/project/project-api.ts b/src/lib/routes/admin-api/project/project-api.ts index 9d2d6d13fc01..bb01f86f1390 100644 --- a/src/lib/routes/admin-api/project/project-api.ts +++ b/src/lib/routes/admin-api/project/project-api.ts @@ -9,7 +9,7 @@ import { serializeDates, } from '../../../types'; import ProjectFeaturesController from '../../../features/feature-toggle/feature-toggle-controller'; -import EnvironmentsController from './environments'; +import EnvironmentsController from '../../../features/project-environments/environments'; import ProjectHealthReport from './health-report'; import ProjectService from '../../../services/project-service'; import VariantsController from './variants'; diff --git a/src/lib/services/access-service.test.ts b/src/lib/services/access-service.test.ts index e9ef00443abc..ddd0edcdbb04 100644 --- a/src/lib/services/access-service.test.ts +++ b/src/lib/services/access-service.test.ts @@ -11,7 +11,7 @@ import { CUSTOM_ROOT_ROLE_TYPE } from '../util/constants'; import FakeGroupStore from '../../test/fixtures/fake-group-store'; import { FakeAccountStore } from '../../test/fixtures/fake-account-store'; import FakeRoleStore from '../../test/fixtures/fake-role-store'; -import FakeEnvironmentStore from '../../test/fixtures/fake-environment-store'; +import FakeEnvironmentStore from '../features/project-environments/fake-environment-store'; import AccessStoreMock from '../../test/fixtures/fake-access-store'; import { GroupService } from '../services/group-service'; import FakeEventStore from '../../test/fixtures/fake-event-store'; diff --git a/src/lib/services/access-service.ts b/src/lib/services/access-service.ts index 74fe31009c64..1f80a5d4f017 100644 --- a/src/lib/services/access-service.ts +++ b/src/lib/services/access-service.ts @@ -24,7 +24,7 @@ import { } from '../types/model'; import { IRoleStore } from '../types/stores/role-store'; import NameExistsError from '../error/name-exists-error'; -import { IEnvironmentStore } from '../types/stores/environment-store'; +import { IEnvironmentStore } from '../features/project-environments/environment-store-type'; import RoleInUseError from '../error/role-in-use-error'; import { roleSchema } from '../schema/role-schema'; import { @@ -606,9 +606,9 @@ export class AccessService { } /* - This method is intended to give a predicable way to fetch + This method is intended to give a predicable way to fetch pre-defined roles defined in the RoleName enum. This method - should not be used to fetch custom root or project roles. + should not be used to fetch custom root or project roles. */ async getPredefinedRole(roleName: RoleName): Promise { const roles = await this.roleStore.getRoles(); diff --git a/src/lib/services/api-token-service.test.ts b/src/lib/services/api-token-service.test.ts index 0301f04c7cff..cf8c5ab1bae9 100644 --- a/src/lib/services/api-token-service.test.ts +++ b/src/lib/services/api-token-service.test.ts @@ -3,7 +3,7 @@ import { createTestConfig } from '../../test/config/test-config'; import { IUnleashConfig } from '../server-impl'; import { ApiTokenType, IApiTokenCreate } from '../types/models/api-token'; import FakeApiTokenStore from '../../test/fixtures/fake-api-token-store'; -import FakeEnvironmentStore from '../../test/fixtures/fake-environment-store'; +import FakeEnvironmentStore from '../features/project-environments/fake-environment-store'; import FakeEventStore from '../../test/fixtures/fake-event-store'; import { API_TOKEN_CREATED, diff --git a/src/lib/services/api-token-service.ts b/src/lib/services/api-token-service.ts index 5ede0b06e585..da968332da0e 100644 --- a/src/lib/services/api-token-service.ts +++ b/src/lib/services/api-token-service.ts @@ -17,7 +17,7 @@ import { import { IApiTokenStore } from '../types/stores/api-token-store'; import { FOREIGN_KEY_VIOLATION } from '../error/db-error'; import BadDataError from '../error/bad-data-error'; -import { IEnvironmentStore } from 'lib/types/stores/environment-store'; +import { IEnvironmentStore } from 'lib/features/project-environments/environment-store-type'; import { constantTimeCompare } from '../util/constantTimeCompare'; import { ApiTokenCreatedEvent, diff --git a/src/lib/services/index.ts b/src/lib/services/index.ts index 18d524c5c18f..03b659647681 100644 --- a/src/lib/services/index.ts +++ b/src/lib/services/index.ts @@ -22,7 +22,7 @@ import SettingService from './setting-service'; import SessionService from './session-service'; import UserFeedbackService from './user-feedback-service'; import FeatureToggleService from '../features/feature-toggle/feature-toggle-service'; -import EnvironmentService from './environment-service'; +import EnvironmentService from '../features/project-environments/environment-service'; import FeatureTagService from './feature-tag-service'; import ProjectHealthService from './project-health-service'; import UserSplashService from './user-splash-service'; @@ -59,6 +59,8 @@ import { } from '../features/change-request-segment-usage-service/createChangeRequestSegmentUsageReadModel'; import ConfigurationRevisionService from '../features/feature-toggle/configuration-revision-service'; import { + createEnvironmentService, + createFakeEnvironmentService, createFakeProjectService, createFeatureToggleService, createProjectService, @@ -229,11 +231,11 @@ export const createServices = ( dependentFeaturesReadModel, dependentFeaturesService, ); - const environmentService = new EnvironmentService( - stores, - config, - eventService, - ); + const transactionalEnvironmentService = db + ? withTransactional(createEnvironmentService(config), db) + : withFakeTransactional(createFakeEnvironmentService(config)); + const environmentService = transactionalEnvironmentService; + const featureTagService = new FeatureTagService( stores, config, @@ -340,6 +342,7 @@ export const createServices = ( resetTokenService, eventService, environmentService, + transactionalEnvironmentService, settingService, sessionService, userFeedbackService, diff --git a/src/lib/services/state-service.ts b/src/lib/services/state-service.ts index 94541a45e314..7b4fdb82c57f 100644 --- a/src/lib/services/state-service.ts +++ b/src/lib/services/state-service.ts @@ -45,7 +45,7 @@ import { ITagStore } from '../types/stores/tag-store'; import { IStrategy, IStrategyStore } from '../types/stores/strategy-store'; import { IFeatureToggleStore } from '../features/feature-toggle/types/feature-toggle-store-type'; import { IFeatureStrategiesStore } from '../features/feature-toggle/types/feature-toggle-strategies-store-type'; -import { IEnvironmentStore } from '../types/stores/environment-store'; +import { IEnvironmentStore } from '../features/project-environments/environment-store-type'; import { IFeatureEnvironmentStore } from '../types/stores/feature-environment-store'; import { IUnleashStores } from '../types/stores'; import { DEFAULT_ENV } from '../util/constants'; diff --git a/src/lib/types/services.ts b/src/lib/types/services.ts index 80b0e1069cb4..d689bc0aab2a 100644 --- a/src/lib/types/services.ts +++ b/src/lib/types/services.ts @@ -19,7 +19,7 @@ import SettingService from '../services/setting-service'; import SessionService from '../services/session-service'; import UserFeedbackService from '../services/user-feedback-service'; import FeatureToggleService from '../features/feature-toggle/feature-toggle-service'; -import EnvironmentService from '../services/environment-service'; +import EnvironmentService from '../features/project-environments/environment-service'; import FeatureTagService from '../services/feature-tag-service'; import ProjectHealthService from '../services/project-health-service'; import ClientMetricsServiceV2 from '../services/client-metrics/metrics-service-v2'; @@ -62,6 +62,7 @@ export interface IUnleashServices { contextService: ContextService; emailService: EmailService; environmentService: EnvironmentService; + transactionalEnvironmentService: WithTransactional; eventService: EventService; edgeService: EdgeService; featureTagService: FeatureTagService; diff --git a/src/lib/types/stores.ts b/src/lib/types/stores.ts index f5b30feece98..2d882ef941f5 100644 --- a/src/lib/types/stores.ts +++ b/src/lib/types/stores.ts @@ -19,7 +19,7 @@ import { IResetTokenStore } from './stores/reset-token-store'; import { IUserFeedbackStore } from './stores/user-feedback-store'; import { IFeatureEnvironmentStore } from './stores/feature-environment-store'; import { IFeatureStrategiesStore } from '../features/feature-toggle/types/feature-toggle-strategies-store-type'; -import { IEnvironmentStore } from './stores/environment-store'; +import { IEnvironmentStore } from '../features/project-environments/environment-store-type'; import { IFeatureToggleClientStore } from '../features/client-feature-toggles/types/client-feature-toggle-store-type'; import { IClientMetricsStoreV2 } from './stores/client-metrics-store-v2'; import { IUserSplashStore } from './stores/user-splash-store'; diff --git a/src/test/e2e/api/admin/environment.test.ts b/src/test/e2e/api/admin/environment.test.ts index 7219c223d5a7..f1673c6c9d29 100644 --- a/src/test/e2e/api/admin/environment.test.ts +++ b/src/test/e2e/api/admin/environment.test.ts @@ -11,13 +11,17 @@ let db: ITestDb; beforeAll(async () => { db = await dbInit('environment_api_serial', getLogger); - app = await setupAppWithCustomConfig(db.stores, { - experimental: { - flags: { - strictSchemaValidation: true, + app = await setupAppWithCustomConfig( + db.stores, + { + experimental: { + flags: { + strictSchemaValidation: true, + }, }, }, - }); + db.rawDatabase, + ); }); afterAll(async () => { diff --git a/src/test/e2e/api/admin/state.e2e.test.ts b/src/test/e2e/api/admin/state.e2e.test.ts index 13855adfc2f0..3f353ca6b0ae 100644 --- a/src/test/e2e/api/admin/state.e2e.test.ts +++ b/src/test/e2e/api/admin/state.e2e.test.ts @@ -1,5 +1,9 @@ import dbInit, { ITestDb } from '../../helpers/database-init'; -import { IUnleashTest, setupApp } from '../../helpers/test-helper'; +import { + IUnleashTest, + setupApp, + setupAppWithCustomConfig, +} from '../../helpers/test-helper'; import getLogger from '../../../fixtures/no-logger'; import { DEFAULT_ENV } from '../../../../lib/util/constants'; import { collectIds } from '../../../../lib/util/collect-ids'; @@ -12,7 +16,17 @@ let db: ITestDb; beforeAll(async () => { db = await dbInit('state_api_serial', getLogger); - app = await setupApp(db.stores); + app = await setupAppWithCustomConfig( + db.stores, + { + experimental: { + flags: { + strictSchemaValidation: true, + }, + }, + }, + db.rawDatabase, + ); }); afterAll(async () => { diff --git a/src/test/e2e/helpers/database-init.ts b/src/test/e2e/helpers/database-init.ts index 2a51f9dba216..4121c6a69f70 100644 --- a/src/test/e2e/helpers/database-init.ts +++ b/src/test/e2e/helpers/database-init.ts @@ -6,7 +6,7 @@ import { createTestConfig } from '../../config/test-config'; import dbState from './database.json'; import { LogProvider } from '../../../lib/logger'; import noLoggerProvider from '../../fixtures/no-logger'; -import EnvironmentStore from '../../../lib/db/environment-store'; +import EnvironmentStore from '../../../lib/features/project-environments/environment-store'; import { IUnleashStores } from '../../../lib/types'; import { IFeatureEnvironmentStore } from '../../../lib/types/stores/feature-environment-store'; import { DEFAULT_ENV } from '../../../lib/util/constants'; diff --git a/src/test/e2e/services/project-service.e2e.test.ts b/src/test/e2e/services/project-service.e2e.test.ts index 9c6b0c7ffe2c..1f52daa981a3 100644 --- a/src/test/e2e/services/project-service.e2e.test.ts +++ b/src/test/e2e/services/project-service.e2e.test.ts @@ -7,7 +7,7 @@ import { MOVE_FEATURE_TOGGLE } from '../../../lib/types/permissions'; import { createTestConfig } from '../../config/test-config'; import { RoleName } from '../../../lib/types/model'; import { randomId } from '../../../lib/util/random-id'; -import EnvironmentService from '../../../lib/services/environment-service'; +import EnvironmentService from '../../../lib/features/project-environments/environment-service'; import IncompatibleProjectError from '../../../lib/error/incompatible-project-error'; import { EventService } from '../../../lib/services'; import { FeatureEnvironmentEvent } from '../../../lib/types/events'; diff --git a/src/test/e2e/stores/feature-environment-store.e2e.test.ts b/src/test/e2e/stores/feature-environment-store.e2e.test.ts index 0a499de46a22..c3a91e7d8846 100644 --- a/src/test/e2e/stores/feature-environment-store.e2e.test.ts +++ b/src/test/e2e/stores/feature-environment-store.e2e.test.ts @@ -3,7 +3,7 @@ import dbInit from '../helpers/database-init'; import getLogger from '../../fixtures/no-logger'; import { IFeatureEnvironmentStore } from '../../../lib/types/stores/feature-environment-store'; import { IFeatureToggleStore } from '../../../lib/features/feature-toggle/types/feature-toggle-store-type'; -import { IEnvironmentStore } from '../../../lib/types/stores/environment-store'; +import { IEnvironmentStore } from '../../../lib/features/project-environments/environment-store-type'; let db; let stores: IUnleashStores; diff --git a/src/test/e2e/stores/project-store.e2e.test.ts b/src/test/e2e/stores/project-store.e2e.test.ts index 71a0a2e7f9ec..0494d9486698 100644 --- a/src/test/e2e/stores/project-store.e2e.test.ts +++ b/src/test/e2e/stores/project-store.e2e.test.ts @@ -1,5 +1,5 @@ import { IProjectInsert, IProjectStore } from 'lib/types/stores/project-store'; -import { IEnvironmentStore } from 'lib/types/stores/environment-store'; +import { IEnvironmentStore } from 'lib/features/project-environments/environment-store-type'; import dbInit from '../helpers/database-init'; import getLogger from '../../fixtures/no-logger'; diff --git a/src/test/fixtures/store.ts b/src/test/fixtures/store.ts index 5d022810e51e..5cf12c1d9c9c 100644 --- a/src/test/fixtures/store.ts +++ b/src/test/fixtures/store.ts @@ -13,7 +13,7 @@ import FakeUserStore from './fake-user-store'; import FakeAccessStore from './fake-access-store'; import FakeUserFeedbackStore from './fake-user-feedback-store'; import FakeFeatureTagStore from './fake-feature-tag-store'; -import FakeEnvironmentStore from './fake-environment-store'; +import FakeEnvironmentStore from '../../lib/features/project-environments/fake-environment-store'; import FakeStrategiesStore from './fake-strategies-store'; import { IImportTogglesStore,