Skip to content

Commit

Permalink
refactor: tag type service feature oriented architecture and tx suppo…
Browse files Browse the repository at this point in the history
…rt (#5489)
  • Loading branch information
kwasniew authored Nov 29, 2023
1 parent 5d0904f commit 7a6cb0c
Show file tree
Hide file tree
Showing 21 changed files with 124 additions and 51 deletions.
2 changes: 1 addition & 1 deletion src/lib/db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
44 changes: 44 additions & 0 deletions src/lib/features/tag-type/createTagTypeService.ts
Original file line number Diff line number Diff line change
@@ -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);
};
Original file line number Diff line number Diff line change
@@ -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[] = [];
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Store } from './store';
import { Store } from '../../types/stores/store';

export interface ITagType {
name: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Request, Response } from 'express';
import Controller from '../controller';
import Controller from '../../routes/controller';

import {
CREATE_TAG_TYPE,
Expand All @@ -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,
Expand All @@ -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',
Expand Down Expand Up @@ -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}`)
Expand All @@ -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();
}
Expand All @@ -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;
Original file line number Diff line number Diff line change
@@ -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 () => {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/routes/admin-api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
2 changes: 1 addition & 1 deletion src/lib/services/addon-service.test.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/services/addon-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
12 changes: 10 additions & 2 deletions src/lib/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -321,6 +328,7 @@ export const createServices = (
stateService,
strategyService,
tagTypeService,
transactionalTagTypeService,
tagService,
clientInstanceService,
clientMetricsServiceV2,
Expand Down
5 changes: 4 additions & 1 deletion src/lib/services/state-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
2 changes: 1 addition & 1 deletion src/lib/types/model.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
3 changes: 2 additions & 1 deletion src/lib/types/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -83,6 +83,7 @@ export interface IUnleashServices {
strategyService: StrategyService;
tagService: TagService;
tagTypeService: TagTypeService;
transactionalTagTypeService: WithTransactional<TagTypeService>;
userFeedbackService: UserFeedbackService;
userService: UserService;
versionService: VersionService;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/types/stores.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
2 changes: 1 addition & 1 deletion src/test/e2e/services/addon-service.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down
2 changes: 1 addition & 1 deletion src/test/fixtures/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down

0 comments on commit 7a6cb0c

Please sign in to comment.