mirror of
https://github.com/Unleash/unleash.git
synced 2025-09-10 17:53:36 +02:00
implement transactional for feature toggle store and write a test to prove it
This commit is contained in:
parent
c3b92ca837
commit
dd955c6ede
@ -6,6 +6,7 @@ import NotFoundError from '../error/notfound-error';
|
||||
import { Logger, LogProvider } from '../logger';
|
||||
import { FeatureToggle, FeatureToggleDTO, IVariant } from '../types/model';
|
||||
import { IFeatureToggleStore } from '../types/stores/feature-toggle-store';
|
||||
import { Transactor } from './transactional';
|
||||
|
||||
const FEATURE_COLUMNS = [
|
||||
'name',
|
||||
@ -36,14 +37,18 @@ export interface FeaturesTable {
|
||||
|
||||
const TABLE = 'features';
|
||||
|
||||
export default class FeatureToggleStore implements IFeatureToggleStore {
|
||||
private db: Knex;
|
||||
export default class FeatureToggleStore
|
||||
extends Transactor<FeatureToggleStore>
|
||||
implements IFeatureToggleStore
|
||||
{
|
||||
private db: Knex | Knex.Transaction;
|
||||
|
||||
private logger: Logger;
|
||||
|
||||
private timer: Function;
|
||||
|
||||
constructor(db: Knex, eventBus: EventEmitter, getLogger: LogProvider) {
|
||||
super(db, eventBus, getLogger);
|
||||
this.db = db;
|
||||
this.logger = getLogger('feature-toggle-store.ts');
|
||||
this.timer = (action) =>
|
||||
|
@ -10,7 +10,7 @@ import Group, {
|
||||
IGroupUserModel,
|
||||
} from '../types/group';
|
||||
import Transaction = Knex.Transaction;
|
||||
import { AbstractTransactional } from './transactional';
|
||||
import { Transactor } from './transactional';
|
||||
|
||||
const T = {
|
||||
GROUPS: 'groups',
|
||||
@ -62,10 +62,10 @@ const groupToRow = (group: IStoreGroup) => ({
|
||||
});
|
||||
|
||||
export default class GroupStore
|
||||
extends AbstractTransactional<GroupStore>
|
||||
extends Transactor<GroupStore>
|
||||
implements IGroupStore
|
||||
{
|
||||
private db: Knex;
|
||||
private db: Knex | Knex.Transaction;
|
||||
|
||||
constructor(db: Knex) {
|
||||
super();
|
||||
|
@ -1,9 +1,18 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Transactional } from 'lib/types/stores/transactional';
|
||||
|
||||
export abstract class AbstractTransactional<T> implements Transactional<T> {
|
||||
export abstract class Transactor<T> implements Transactional<T> {
|
||||
args: any[];
|
||||
|
||||
// eslint-disable-next-line
|
||||
constructor(...args: any) {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
transactional(transaction: Knex.Transaction): T {
|
||||
let clone = new (this.constructor as { new (): any })();
|
||||
let clone = new (this.constructor as { new (...args: any[]): any })(
|
||||
...this.args,
|
||||
);
|
||||
for (const attribute in this) {
|
||||
clone[attribute] = this[attribute];
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { FeatureToggle, FeatureToggleDTO, IVariant } from '../model';
|
||||
import { Transactional } from './transactional';
|
||||
import { Store } from './store';
|
||||
|
||||
export interface IFeatureToggleQuery {
|
||||
@ -7,7 +8,9 @@ export interface IFeatureToggleQuery {
|
||||
stale: boolean;
|
||||
}
|
||||
|
||||
export interface IFeatureToggleStore extends Store<FeatureToggle, string> {
|
||||
export interface IFeatureToggleStore
|
||||
extends Store<FeatureToggle, string>,
|
||||
Transactional<IFeatureToggleStore> {
|
||||
count(query?: Partial<IFeatureToggleQuery>): Promise<number>;
|
||||
setLastSeen(toggleNames: string[]): Promise<void>;
|
||||
getProjectId(name: string): Promise<string>;
|
||||
|
@ -5,25 +5,8 @@ let stores;
|
||||
let db: ITestDb;
|
||||
|
||||
beforeAll(async () => {
|
||||
db = await dbInit('group_service_serial', getLogger);
|
||||
db = await dbInit('transactional_serial', getLogger);
|
||||
stores = db.stores;
|
||||
|
||||
await stores.groupStore.create({
|
||||
name: 'dev_group',
|
||||
description: 'dev_group',
|
||||
mappingsSSO: ['dev'],
|
||||
});
|
||||
await stores.groupStore.create({
|
||||
name: 'maintainer_group',
|
||||
description: 'maintainer_group',
|
||||
mappingsSSO: ['maintainer'],
|
||||
});
|
||||
|
||||
await stores.groupStore.create({
|
||||
name: 'admin_group',
|
||||
description: 'admin_group',
|
||||
mappingsSSO: ['admin'],
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
@ -45,3 +28,20 @@ test('should actually do something transactional mode', async () => {
|
||||
});
|
||||
expect(createdGroup).toBeDefined();
|
||||
});
|
||||
|
||||
test('should fail entire transaction if encountering an error', async () => {
|
||||
await db.db.transaction(async (trx) => {
|
||||
const featureDTO = {
|
||||
name: 'SomeUniqueNameThatSoonWontBeUnique',
|
||||
};
|
||||
|
||||
await stores.featureToggleStore
|
||||
.transactional(trx)
|
||||
.create('default', featureDTO);
|
||||
await stores.featureToggleStore
|
||||
.transactional(trx)
|
||||
.create('default', featureDTO);
|
||||
});
|
||||
const toggles = await stores.featureToggleStore.getAll();
|
||||
expect(toggles.length).toBe(0);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user