1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-25 00:07:47 +01:00

refactor: tag type service feature oriented architecture and tx support (#5489)

This commit is contained in:
Mateusz Kwasniewski 2023-11-29 11:44:56 +01:00 committed by GitHub
parent 5d0904f99d
commit 7a6cb0c527
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 124 additions and 51 deletions

View File

@ -11,7 +11,7 @@ import SettingStore from './setting-store';
import UserStore from './user-store';
import ProjectStore from './project-store';
import TagStore from './tag-store';
import TagTypeStore from './tag-type-store';
import TagTypeStore from '../features/tag-type/tag-type-store';
import AddonStore from './addon-store';
import { ApiTokenStore } from './api-token-store';
import SessionStore from './session-store';

View File

@ -18,7 +18,6 @@ import {
ParentFeatureOptionsSchema,
} from '../../openapi';
import { IAuthRequest } from '../../routes/unleash-types';
import { InvalidOperationError } from '../../error';
import { DependentFeaturesService } from './dependent-features-service';
import { WithTransactional } from '../../db/transaction';

View File

@ -4,7 +4,7 @@ import ExportImportService from './export-import-service';
import { ImportTogglesStore } from './import-toggles-store';
import FeatureToggleStore from '../feature-toggle/feature-toggle-store';
import TagStore from '../../db/tag-store';
import TagTypeStore from '../../db/tag-type-store';
import TagTypeStore from '../tag-type/tag-type-store';
import ProjectStore from '../../db/project-store';
import FeatureTagStore from '../../db/feature-tag-store';
import StrategyStore from '../../db/strategy-store';
@ -29,7 +29,7 @@ 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 '../../../test/fixtures/fake-tag-type-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';

View File

@ -1,7 +1,7 @@
import { IImportTogglesStore } from './import-toggles-store-type';
import { AccessService, ContextService, TagTypeService } from '../../services';
import { ContextFieldSchema, ImportTogglesSchema } from '../../openapi';
import { ITagType } from '../../types/stores/tag-type-store';
import { ITagType } from '../tag-type/tag-type-store-type';
import { IUser } from '../../types/user';
import {
CREATE_CONTEXT_FIELD,

View File

@ -0,0 +1,44 @@
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 TagTypeService from './tag-type-service';
import TagTypeStore from './tag-type-store';
import FakeTagTypeStore from './fake-tag-type-store';
export const createTagTypeService =
(config: IUnleashConfig) =>
(db: Db): TagTypeService => {
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 tagTypeStore = new TagTypeStore(db, eventBus, getLogger);
return new TagTypeService({ tagTypeStore }, config, eventService);
};
export const createFakeTagTypeService = (
config: IUnleashConfig,
): TagTypeService => {
const eventStore = new FakeEventStore();
const featureTagStore = new FakeFeatureTagStore();
const eventService = new EventService(
{
eventStore,
featureTagStore,
},
config,
);
const tagTypeStore = new FakeTagTypeStore();
return new TagTypeService({ tagTypeStore }, config, eventService);
};

View File

@ -1,6 +1,6 @@
import { ITagType, ITagTypeStore } from '../../lib/types/stores/tag-type-store';
import { ITagType, ITagTypeStore } from './tag-type-store-type';
const NotFoundError = require('../../lib/error/notfound-error');
const NotFoundError = require('../../error/notfound-error');
export default class FakeTagTypeStore implements ITagTypeStore {
tagTypes: ITagType[] = [];

View File

@ -1,18 +1,18 @@
import NameExistsError from '../error/name-exists-error';
import NameExistsError from '../../error/name-exists-error';
import { tagTypeSchema } from './tag-type-schema';
import { tagTypeSchema } from '../../services/tag-type-schema';
import { IUnleashStores } from '../types/stores';
import { IUnleashStores } from '../../types/stores';
import {
TAG_TYPE_CREATED,
TAG_TYPE_DELETED,
TAG_TYPE_UPDATED,
} from '../types/events';
} from '../../types/events';
import { Logger } from '../logger';
import { ITagType, ITagTypeStore } from '../types/stores/tag-type-store';
import { IUnleashConfig } from '../types/option';
import EventService from './event-service';
import { Logger } from '../../logger';
import { ITagType, ITagTypeStore } from './tag-type-store-type';
import { IUnleashConfig } from '../../types/option';
import EventService from '../../services/event-service';
export default class TagTypeService {
private tagTypeStore: ITagTypeStore;

View File

@ -1,4 +1,4 @@
import { Store } from './store';
import { Store } from '../../types/stores/store';
export interface ITagType {
name: string;

View File

@ -1,10 +1,10 @@
import { EventEmitter } from 'events';
import { LogProvider, Logger } from '../logger';
import { DB_TIME } from '../metric-events';
import metricsHelper from '../util/metrics-helper';
import NotFoundError from '../error/notfound-error';
import { ITagType, ITagTypeStore } from '../types/stores/tag-type-store';
import { Db } from './db';
import { LogProvider, Logger } from '../../logger';
import { DB_TIME } from '../../metric-events';
import metricsHelper from '../../util/metrics-helper';
import NotFoundError from '../../error/notfound-error';
import { ITagType, ITagTypeStore } from './tag-type-store-type';
import { Db } from '../../db/db';
const COLUMNS = ['name', 'description', 'icon'];
const TABLE = 'tag_types';

View File

@ -1,5 +1,5 @@
import { Request, Response } from 'express';
import Controller from '../controller';
import Controller from '../../routes/controller';
import {
CREATE_TAG_TYPE,
@ -10,9 +10,9 @@ import {
import { extractUsername } from '../../util/extract-user';
import { IUnleashConfig } from '../../types/option';
import { IUnleashServices } from '../../types/services';
import TagTypeService from '../../services/tag-type-service';
import TagTypeService from './tag-type-service';
import { Logger } from '../../logger';
import { IAuthRequest } from '../unleash-types';
import { IAuthRequest } from '../../routes/unleash-types';
import { createRequestSchema } from '../../openapi/util/create-request-schema';
import {
createResponseSchema,
@ -30,26 +30,30 @@ import {
emptyResponse,
getStandardResponses,
} from '../../openapi/util/standard-responses';
import { WithTransactional } from '../../db/transaction';
const version = 1;
class TagTypeController extends Controller {
private logger: Logger;
private tagTypeService: TagTypeService;
private tagTypeService: WithTransactional<TagTypeService>;
private openApiService: OpenApiService;
constructor(
config: IUnleashConfig,
{
tagTypeService,
transactionalTagTypeService,
openApiService,
}: Pick<IUnleashServices, 'tagTypeService' | 'openApiService'>,
}: Pick<
IUnleashServices,
'transactionalTagTypeService' | 'openApiService'
>,
) {
super(config);
this.logger = config.getLogger('/admin-api/tag-type.js');
this.tagTypeService = tagTypeService;
this.tagTypeService = transactionalTagTypeService;
this.openApiService = openApiService;
this.route({
method: 'get',
@ -198,9 +202,8 @@ class TagTypeController extends Controller {
res: Response,
): Promise<void> {
const userName = extractUsername(req);
const tagType = await this.tagTypeService.createTagType(
req.body,
userName,
const tagType = await this.tagTypeService.transactional((service) =>
service.createTagType(req.body, userName),
);
res.status(201)
.header('location', `tag-types/${tagType.name}`)
@ -215,9 +218,8 @@ class TagTypeController extends Controller {
const { name } = req.params;
const userName = extractUsername(req);
await this.tagTypeService.updateTagType(
{ name, description, icon },
userName,
await this.tagTypeService.transactional((service) =>
service.updateTagType({ name, description, icon }, userName),
);
res.status(200).end();
}
@ -232,9 +234,12 @@ class TagTypeController extends Controller {
async deleteTagType(req: IAuthRequest, res: Response): Promise<void> {
const { name } = req.params;
const userName = extractUsername(req);
await this.tagTypeService.deleteTagType(name, userName);
await this.tagTypeService.transactional((service) =>
service.deleteTagType(name, userName),
);
res.status(200).end();
}
}
export default TagTypeController;
module.exports = TagTypeController;

View File

@ -1,13 +1,26 @@
import dbInit from '../../helpers/database-init';
import { setupApp } from '../../helpers/test-helper';
import getLogger from '../../../fixtures/no-logger';
import dbInit from '../../../test/e2e/helpers/database-init';
import {
setupApp,
setupAppWithCustomConfig,
} from '../../../test/e2e/helpers/test-helper';
import getLogger from '../../../test/fixtures/no-logger';
let app;
let db;
beforeAll(async () => {
db = await dbInit('tag_types_api_serial', getLogger);
app = await setupApp(db.stores);
app = await setupAppWithCustomConfig(
db.stores,
{
experimental: {
flags: {
strictSchemaValidation: true,
},
},
},
db.rawDatabase,
);
});
afterAll(async () => {

View File

@ -13,7 +13,7 @@ import { ContextController } from './context';
import ClientMetricsController from './client-metrics';
import StateController from './state';
import TagController from './tag';
import TagTypeController from './tag-type';
import TagTypeController from '../../features/tag-type/tag-type';
import AddonController from './addon';
import { ApiTokenController } from './api-token';
import UserAdminController from './user-admin';

View File

@ -1,7 +1,7 @@
import { ValidationError } from 'joi';
import getLogger from '../../test/fixtures/no-logger';
import TagTypeService from './tag-type-service';
import TagTypeService from '../features/tag-type/tag-type-service';
import {
ADDON_CONFIG_CREATED,
ADDON_CONFIG_DELETED,

View File

@ -6,7 +6,7 @@ import { addonSchema } from './addon-schema';
import NameExistsError from '../error/name-exists-error';
import { IFeatureToggleStore } from '../features/feature-toggle/types/feature-toggle-store-type';
import { Logger } from '../logger';
import TagTypeService from './tag-type-service';
import TagTypeService from '../features/tag-type/tag-type-service';
import { IAddon, IAddonDto, IAddonStore } from '../types/stores/addon-store';
import { IUnleashStores, IUnleashConfig } from '../types';
import { IAddonDefinition } from '../types/model';

View File

@ -7,7 +7,7 @@ import ProjectService from './project-service';
import StateService from './state-service';
import ClientInstanceService from './client-metrics/instance-service';
import ClientMetricsServiceV2 from './client-metrics/metrics-service-v2';
import TagTypeService from './tag-type-service';
import TagTypeService from '../features/tag-type/tag-type-service';
import TagService from './tag-service';
import StrategyService from './strategy-service';
import AddonService from './addon-service';
@ -98,6 +98,10 @@ import {
createFakeFeatureSearchService,
} from '../features/feature-search/createFeatureSearchService';
import { FeatureSearchService } from '../features/feature-search/feature-search-service';
import {
createFakeTagTypeService,
createTagTypeService,
} from '../features/tag-type/createTagTypeService';
export const createServices = (
stores: IUnleashStores,
@ -144,7 +148,10 @@ export const createServices = (
const stateService = new StateService(stores, config, eventService);
const strategyService = new StrategyService(stores, config, eventService);
const tagService = new TagService(stores, config, eventService);
const tagTypeService = new TagTypeService(stores, config, eventService);
const transactionalTagTypeService = db
? withTransactional(createTagTypeService(config), db)
: withFakeTransactional(createFakeTagTypeService(config));
const tagTypeService = transactionalTagTypeService;
const addonService = new AddonService(
stores,
config,
@ -321,6 +328,7 @@ export const createServices = (
stateService,
strategyService,
tagTypeService,
transactionalTagTypeService,
tagService,
clientInstanceService,
clientMetricsServiceV2,

View File

@ -37,7 +37,10 @@ import {
IFeatureTagStore,
} from '../types/stores/feature-tag-store';
import { IProjectStore } from '../types/stores/project-store';
import { ITagType, ITagTypeStore } from '../types/stores/tag-type-store';
import {
ITagType,
ITagTypeStore,
} from '../features/tag-type/tag-type-store-type';
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';

View File

@ -1,4 +1,4 @@
import { ITagType } from './stores/tag-type-store';
import { ITagType } from '../features/tag-type/tag-type-store-type';
import { LogProvider } from '../logger';
import { IRole } from './stores/access-store';
import { IUser } from './user';

View File

@ -3,7 +3,7 @@ import AddonService from '../services/addon-service';
import ProjectService from '../services/project-service';
import StateService from '../services/state-service';
import StrategyService from '../services/strategy-service';
import TagTypeService from '../services/tag-type-service';
import TagTypeService from '../features/tag-type/tag-type-service';
import TagService from '../services/tag-service';
import ClientInstanceService from '../services/client-metrics/instance-service';
import ContextService from '../services/context-service';
@ -83,6 +83,7 @@ export interface IUnleashServices {
strategyService: StrategyService;
tagService: TagService;
tagTypeService: TagTypeService;
transactionalTagTypeService: WithTransactional<TagTypeService>;
userFeedbackService: UserFeedbackService;
userService: UserService;
versionService: VersionService;

View File

@ -9,7 +9,7 @@ import { IContextFieldStore } from './stores/context-field-store';
import { ISettingStore } from './stores/settings-store';
import { ISessionStore } from './stores/session-store';
import { ITagStore } from './stores/tag-store';
import { ITagTypeStore } from './stores/tag-type-store';
import { ITagTypeStore } from '../features/tag-type/tag-type-store-type';
import { IFeatureTagStore } from './stores/feature-tag-store';
import { IUserStore } from './stores/user-store';
import { IAddonStore } from './stores/addon-store';

View File

@ -5,7 +5,7 @@ import AddonService from '../../../lib/services/addon-service';
import { IUnleashStores } from '../../../lib/types';
import SimpleAddon from '../../../lib/services/addon-service-test-simple-addon';
import TagTypeService from '../../../lib/services/tag-type-service';
import TagTypeService from '../../../lib/features/tag-type/tag-type-service';
import { FEATURE_CREATED } from '../../../lib/types/events';
import { EventService } from '../../../lib/services';

View File

@ -3,7 +3,7 @@ import FakeClientInstanceStore from './fake-client-instance-store';
import FakeClientApplicationsStore from './fake-client-applications-store';
import FakeFeatureToggleStore from '../../lib/features/feature-toggle/fakes/fake-feature-toggle-store';
import FakeTagStore from './fake-tag-store';
import FakeTagTypeStore from './fake-tag-type-store';
import FakeTagTypeStore from '../../lib/features/tag-type/fake-tag-type-store';
import FakeEventStore from './fake-event-store';
import FakeContextFieldStore from './fake-context-field-store';
import FakeSettingStore from './fake-setting-store';