From 4037fdf8ba83d99638c8d0d0bc6f838272e1fed1 Mon Sep 17 00:00:00 2001 From: ivaosthu Date: Sat, 5 Nov 2016 10:16:48 +0100 Subject: [PATCH] cleanup api-db-stores a bit --- .../lib/db/{event.js => event-store.js} | 39 ++++++----- .../{feature.js => feature-toggle-store.js} | 70 +++++++++---------- packages/unleash-api/lib/db/index.js | 22 ++++-- .../lib/db/{strategy.js => strategy-store.js} | 59 ++++++++-------- packages/unleash-api/lib/event-store.js | 15 ---- packages/unleash-api/lib/routes/event.js | 6 +- .../unleash-api/lib/routes/feature-archive.js | 6 +- packages/unleash-api/lib/routes/feature.js | 18 ++--- packages/unleash-api/lib/routes/strategy.js | 14 ++-- packages/unleash-api/server-impl.js | 20 +++--- packages/unleash-api/test/e2e/test-helper.js | 22 +++--- 11 files changed, 142 insertions(+), 149 deletions(-) rename packages/unleash-api/lib/db/{event.js => event-store.js} (59%) rename packages/unleash-api/lib/db/{feature.js => feature-toggle-store.js} (59%) rename packages/unleash-api/lib/db/{strategy.js => strategy-store.js} (50%) delete mode 100644 packages/unleash-api/lib/event-store.js diff --git a/packages/unleash-api/lib/db/event.js b/packages/unleash-api/lib/db/event-store.js similarity index 59% rename from packages/unleash-api/lib/db/event.js rename to packages/unleash-api/lib/db/event-store.js index 5aba0ddaff..8773ad0181 100644 --- a/packages/unleash-api/lib/db/event.js +++ b/packages/unleash-api/lib/db/event-store.js @@ -1,36 +1,45 @@ 'use strict'; +const { EventEmitter } = require('events'); + const EVENT_COLUMNS = ['id', 'type', 'created_by', 'created_at', 'data']; -module.exports = function (db) { - function storeEvent (event) { - return db('events').insert({ +class EventStore extends EventEmitter { + + constructor (db) { + super(); + this.db = db; + } + + store (event) { + return this.db('events').insert({ type: event.type, created_by: event.createdBy, // eslint-disable-line data: event.data, - }); + }) + .then(() => this.emit(event.type, event)); } - function getEvents () { - return db + getEvents () { + return this.db .select(EVENT_COLUMNS) .from('events') .limit(100) .orderBy('created_at', 'desc') - .map(rowToEvent); + .map(this.rowToEvent); } - function getEventsFilterByName (name) { - return db + getEventsFilterByName (name) { + return this.db .select(EVENT_COLUMNS) .from('events') .limit(100) .whereRaw('data ->> \'name\' = ?', [name]) .orderBy('created_at', 'desc') - .map(rowToEvent); + .map(this.rowToEvent); } - function rowToEvent (row) { + rowToEvent (row) { return { id: row.id, type: row.type, @@ -39,11 +48,7 @@ module.exports = function (db) { data: row.data, }; } - - return { - store: storeEvent, - getEvents, - getEventsFilterByName, - }; }; +module.exports = EventStore; + diff --git a/packages/unleash-api/lib/db/feature.js b/packages/unleash-api/lib/db/feature-toggle-store.js similarity index 59% rename from packages/unleash-api/lib/db/feature.js rename to packages/unleash-api/lib/db/feature-toggle-store.js index 0c8f56451b..c0090dc7ec 100644 --- a/packages/unleash-api/lib/db/feature.js +++ b/packages/unleash-api/lib/db/feature-toggle-store.js @@ -5,42 +5,43 @@ const logger = require('../logger'); const NotFoundError = require('../error/notfound-error'); const FEATURE_COLUMNS = ['name', 'description', 'enabled', 'strategies']; -module.exports = function (db, eventStore) { - eventStore.on(eventType.featureCreated, event => createFeature(event.data)); +class FeatureToggleStore { + constructor (db, eventStore) { + this.db = db; + eventStore.on(eventType.featureCreated, event => this._createFeature(event.data)); + eventStore.on(eventType.featureUpdated, event => this._updateFeature(event.data)); + eventStore.on(eventType.featureArchived, event => this._archiveFeature(event.data)); + eventStore.on(eventType.featureRevived, event => this._reviveFeature(event.data)); + } + - eventStore.on(eventType.featureUpdated, event => updateFeature(event.data)); - - eventStore.on(eventType.featureArchived, event => archiveFeature(event.data)); - - eventStore.on(eventType.featureRevived, event => reviveFeature(event.data)); - - function getFeatures () { - return db + getFeatures () { + return this.db .select(FEATURE_COLUMNS) .from('features') .where({ archived: 0 }) .orderBy('name', 'asc') - .map(rowToFeature); + .map(this.rowToFeature); } - function getFeature (name) { - return db + getFeature (name) { + return this.db .first(FEATURE_COLUMNS) .from('features') .where({ name }) - .then(rowToFeature); + .then(this.rowToFeature); } - function getArchivedFeatures () { - return db + getArchivedFeatures () { + return this.db .select(FEATURE_COLUMNS) .from('features') .where({ archived: 1 }) .orderBy('name', 'asc') - .map(rowToFeature); + .map(this.rowToFeature); } - function rowToFeature (row) { + rowToFeature (row) { if (!row) { throw new NotFoundError('No feature toggle found'); } @@ -52,7 +53,7 @@ module.exports = function (db, eventStore) { }; } - function eventDataToRow (data) { + eventDataToRow (data) { return { name: data.name, description: data.description, @@ -62,25 +63,25 @@ module.exports = function (db, eventStore) { }; } - function createFeature (data) { - return db('features') - .insert(eventDataToRow(data)) + _createFeature (data) { + return this.db('features') + .insert(this.eventDataToRow(data)) .catch(err => { logger.error('Could not insert feature, error was: ', err); }); } - function updateFeature (data) { - return db('features') + _updateFeature (data) { + return this.db('features') .where({ name: data.name }) - .update(eventDataToRow(data)) + .update(this.eventDataToRow(data)) .catch(err => { logger.error('Could not update feature, error was: ', err); }); } - function archiveFeature (data) { - return db('features') + _archiveFeature (data) { + return this.db('features') .where({ name: data.name }) .update({ archived: 1 }) .catch(err => { @@ -88,21 +89,14 @@ module.exports = function (db, eventStore) { }); } - function reviveFeature (data) { - return db('features') + _reviveFeature (data) { + return this.db('features') .where({ name: data.name }) .update({ archived: 0, enabled: 0 }) .catch(err => { logger.error('Could not archive feature, error was: ', err); }); } - - - return { - getFeatures, - getFeature, - getArchivedFeatures, - _createFeature: createFeature, // visible for testing - _updateFeature: updateFeature, // visible for testing - }; }; + +module.exports = FeatureToggleStore; diff --git a/packages/unleash-api/lib/db/index.js b/packages/unleash-api/lib/db/index.js index f369160f9a..cd5ff06811 100644 --- a/packages/unleash-api/lib/db/index.js +++ b/packages/unleash-api/lib/db/index.js @@ -1,13 +1,21 @@ 'use strict'; -const eventDbCreator = require('./event'); +const EventStore = require('./event-store'); +const FeatureToggleStore = require('./feature-toggle-store'); +const StrategyStore = require('./strategy-store'); const clientInstancesDbCreator = require('./client-instances'); const clientMetricsDbCreator = require('./client-metrics'); const clientStrategiesDbCreator = require('./client-strategies'); -module.exports = (db) => ({ - eventDb: eventDbCreator(db), - clientInstancesDb: clientInstancesDbCreator(db), - clientMetricsDb: clientMetricsDbCreator(db), - clientStrategiesDb: clientStrategiesDbCreator(db), -}); +module.exports = (db) => { + const eventStore = new EventStore(db); + + return { + eventStore, + featureToggleStore: new FeatureToggleStore(db, eventStore), + strategyStore: new StrategyStore(db, eventStore), + clientInstancesDb: clientInstancesDbCreator(db), + clientMetricsDb: clientMetricsDbCreator(db), + clientStrategiesDb: clientStrategiesDbCreator(db), + }; +}; diff --git a/packages/unleash-api/lib/db/strategy.js b/packages/unleash-api/lib/db/strategy-store.js similarity index 50% rename from packages/unleash-api/lib/db/strategy.js rename to packages/unleash-api/lib/db/strategy-store.js index cc582d3df1..b56864d9e8 100644 --- a/packages/unleash-api/lib/db/strategy.js +++ b/packages/unleash-api/lib/db/strategy-store.js @@ -4,36 +4,39 @@ const eventType = require('../event-type'); const logger = require('../logger'); const NotFoundError = require('../error/notfound-error'); const STRATEGY_COLUMNS = ['name', 'description', 'parameters_template']; +const TABLE = 'strategies'; -module.exports = function (db, eventStore) { - eventStore.on(eventType.strategyCreated, event => createStrategy(event.data)); +class StrategyStore { + constructor (db, eventStore) { + this.db = db; + eventStore.on(eventType.strategyCreated, event => this._createStrategy(event.data)); + eventStore.on(eventType.strategyDeleted, event => { + db(TABLE) + .where('name', event.data.name) + .del() + .catch(err => { + logger.error('Could not delete strategy, error was: ', err); + }); + }); + } - eventStore.on(eventType.strategyDeleted, event => { - db('strategies') - .where('name', event.data.name) - .del() - .catch(err => { - logger.error('Could not delete strategy, error was: ', err); - }); - }); - - function getStrategies () { - return db + getStrategies () { + return this.db .select(STRATEGY_COLUMNS) - .from('strategies') + .from(TABLE) .orderBy('created_at', 'asc') - .map(rowToStrategy); + .map(this.rowToStrategy); } - function getStrategy (name) { - return db + getStrategy (name) { + return this.db .first(STRATEGY_COLUMNS) - .from('strategies') + .from(TABLE) .where({ name }) - .then(rowToStrategy); + .then(this.rowToStrategy); } - function rowToStrategy (row) { + rowToStrategy (row) { if (!row) { throw new NotFoundError('No strategy found'); } @@ -45,7 +48,7 @@ module.exports = function (db, eventStore) { }; } - function eventDataToRow (data) { + eventDataToRow (data) { return { name: data.name, description: data.description, @@ -53,18 +56,14 @@ module.exports = function (db, eventStore) { }; } - function createStrategy (data) { - db('strategies') - .insert(eventDataToRow(data)) + _createStrategy (data) { + this.db(TABLE) + .insert(this.eventDataToRow(data)) .catch(err => { logger.error('Could not insert strategy, error was: ', err); }); } - - return { - getStrategies, - getStrategy, - _createStrategy: createStrategy, // visible for testing - }; }; +module.exports = StrategyStore; + diff --git a/packages/unleash-api/lib/event-store.js b/packages/unleash-api/lib/event-store.js deleted file mode 100644 index 30b163de45..0000000000 --- a/packages/unleash-api/lib/event-store.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -const EventEmitter = require('events').EventEmitter; - -module.exports = class EventStore extends EventEmitter { - constructor (eventDb) { - super(); - this.eventDb = eventDb; - } - - create (event) { - return this.eventDb.store(event).then(() => this.emit(event.type, event)); - } -}; - diff --git a/packages/unleash-api/lib/routes/event.js b/packages/unleash-api/lib/routes/event.js index 7f77507511..81bef95cd8 100644 --- a/packages/unleash-api/lib/routes/event.js +++ b/packages/unleash-api/lib/routes/event.js @@ -4,17 +4,17 @@ const eventDiffer = require('../event-differ'); const version = 1; module.exports = function (app, config) { - const eventDb = config.eventDb; + const eventStore = config.eventStore; app.get('/events', (req, res) => { - eventDb.getEvents().then(events => { + eventStore.getEvents().then(events => { eventDiffer.addDiffs(events); res.json({ version, events }); }); }); app.get('/events/:name', (req, res) => { - eventDb.getEventsFilterByName(req.params.name).then(events => { + eventStore.getEventsFilterByName(req.params.name).then(events => { if (events) { eventDiffer.addDiffs(events); res.json(events); diff --git a/packages/unleash-api/lib/routes/feature-archive.js b/packages/unleash-api/lib/routes/feature-archive.js index 56504c3455..a91a099686 100644 --- a/packages/unleash-api/lib/routes/feature-archive.js +++ b/packages/unleash-api/lib/routes/feature-archive.js @@ -6,11 +6,11 @@ const ValidationError = require('../error/validation-error'); const validateRequest = require('../error/validate-request'); module.exports = function (app, config) { - const featureDb = config.featureDb; + const featureToggleStore = config.featureToggleStore; const eventStore = config.eventStore; app.get('/archive/features', (req, res) => { - featureDb.getArchivedFeatures().then(archivedFeatures => { + featureToggleStore.getArchivedFeatures().then(archivedFeatures => { res.json({ features: archivedFeatures }); }); }); @@ -19,7 +19,7 @@ module.exports = function (app, config) { req.checkBody('name', 'Name is required').notEmpty(); validateRequest(req) - .then(() => eventStore.create({ + .then(() => eventStore.store({ type: eventType.featureRevived, createdBy: req.connection.remoteAddress, data: req.body, diff --git a/packages/unleash-api/lib/routes/feature.js b/packages/unleash-api/lib/routes/feature.js index 0c03044d4e..2569a00ad2 100644 --- a/packages/unleash-api/lib/routes/feature.js +++ b/packages/unleash-api/lib/routes/feature.js @@ -13,17 +13,17 @@ const legacyFeatureMapper = require('../helper/legacy-feature-mapper'); const version = 1; module.exports = function (app, config) { - const featureDb = config.featureDb; + const featureToggleStore = config.featureToggleStore; const eventStore = config.eventStore; app.get('/features', (req, res) => { - featureDb.getFeatures() + featureToggleStore.getFeatures() .then((features) => features.map(legacyFeatureMapper.addOldFields)) .then(features => res.json({ version, features })); }); app.get('/features/:featureName', (req, res) => { - featureDb.getFeature(req.params.featureName) + featureToggleStore.getFeature(req.params.featureName) .then(legacyFeatureMapper.addOldFields) .then(feature => res.json(feature).end()) .catch(() => res.status(404).json({ error: 'Could not find feature' })); @@ -36,7 +36,7 @@ module.exports = function (app, config) { validateRequest(req) .then(validateFormat) .then(validateUniqueName) - .then(() => eventStore.create({ + .then(() => eventStore.store({ type: eventType.featureCreated, createdBy: extractUser(req), data: legacyFeatureMapper.toNewFormat(req.body), @@ -61,8 +61,8 @@ module.exports = function (app, config) { updatedFeature.name = featureName; - featureDb.getFeature(featureName) - .then(() => eventStore.create({ + featureToggleStore.getFeature(featureName) + .then(() => eventStore.store({ type: eventType.featureUpdated, createdBy: userName, data: updatedFeature, @@ -79,8 +79,8 @@ module.exports = function (app, config) { const featureName = req.params.featureName; const userName = extractUser(req); - featureDb.getFeature(featureName) - .then(() => eventStore.create({ + featureToggleStore.getFeature(featureName) + .then(() => eventStore.store({ type: eventType.featureArchived, createdBy: userName, data: { @@ -97,7 +97,7 @@ module.exports = function (app, config) { function validateUniqueName (req) { return new BPromise((resolve, reject) => { - featureDb.getFeature(req.body.name) + featureToggleStore.getFeature(req.body.name) .then(() => { reject(new NameExistsError('Feature name already exist')); }, () => { diff --git a/packages/unleash-api/lib/routes/strategy.js b/packages/unleash-api/lib/routes/strategy.js index 2c3eeeb2d6..c0320c863c 100644 --- a/packages/unleash-api/lib/routes/strategy.js +++ b/packages/unleash-api/lib/routes/strategy.js @@ -11,17 +11,17 @@ const extractUser = require('../extract-user'); const version = 1; module.exports = function (app, config) { - const strategyDb = config.strategyDb; + const strategyStore = config.strategyStore; const eventStore = config.eventStore; app.get('/strategies', (req, res) => { - strategyDb.getStrategies().then(strategies => { + strategyStore.getStrategies().then(strategies => { res.json({ version, strategies }); }); }); app.get('/strategies/:name', (req, res) => { - strategyDb.getStrategy(req.params.name) + strategyStore.getStrategy(req.params.name) .then(strategy => { res.json(strategy); }) @@ -33,8 +33,8 @@ module.exports = function (app, config) { app.delete('/strategies/:name', (req, res) => { const strategyName = req.params.name; - strategyDb.getStrategy(strategyName) - .then(() => eventStore.create({ + strategyStore.getStrategy(strategyName) + .then(() => eventStore.store({ type: eventType.strategyDeleted, createdBy: extractUser(req), data: { @@ -61,7 +61,7 @@ module.exports = function (app, config) { validateRequest(req) .then(validateStrategyName) - .then(() => eventStore.create({ + .then(() => eventStore.store({ type: eventType.strategyCreated, createdBy: extractUser(req), data: newStrategy, @@ -81,7 +81,7 @@ module.exports = function (app, config) { function validateStrategyName (req) { return new BPromise((resolve, reject) => { - strategyDb.getStrategy(req.body.name) + strategyStore.getStrategy(req.body.name) .then(() => { reject(new NameExistsError('Feature name already exist')); }, () => { diff --git a/packages/unleash-api/server-impl.js b/packages/unleash-api/server-impl.js index 3be983f29f..1611329480 100644 --- a/packages/unleash-api/server-impl.js +++ b/packages/unleash-api/server-impl.js @@ -13,23 +13,23 @@ function createApp (options) { const db = require('./lib/db/db-pool')(options.databaseUri); // Database dependecies (statefull) - const { eventDb, clientInstancesDb, clientMetricsDb, clientStrategiesDb } = require('./lib/db')(db); - - // Needs some cleanup! - const EventStore = require('./lib/event-store'); - const eventStore = new EventStore(eventDb); - const featureDb = require('./lib/db/feature')(db, eventStore); - const strategyDb = require('./lib/db/strategy')(db, eventStore); + const { + eventStore, + featureToggleStore, + strategyStore, + clientInstancesDb, + clientMetricsDb, + clientStrategiesDb, + } = require('./lib/db')(db); const config = { baseUriPath: options.baseUriPath, port: options.port, publicFolder: options.publicFolder, db, - eventDb, eventStore, - featureDb, - strategyDb, + featureToggleStore, + strategyStore, clientMetricsDb, clientStrategiesDb, clientInstancesDb, diff --git a/packages/unleash-api/test/e2e/test-helper.js b/packages/unleash-api/test/e2e/test-helper.js index e60a8c6aea..b5337df1b9 100644 --- a/packages/unleash-api/test/e2e/test-helper.js +++ b/packages/unleash-api/test/e2e/test-helper.js @@ -6,20 +6,22 @@ const BPromise = require('bluebird'); let request = require('supertest'); const databaseUri = require('./database-config').getDatabaseUri(); const knex = require('../../lib/db/db-pool')(databaseUri); -const { eventDb, clientInstancesDb, clientStrategiesDb, clientMetricsDb } = require('../../lib/db')(knex); -const EventStore = require('../../lib/event-store'); -const eventStore = new EventStore(eventDb); -const featureDb = require('../../lib/db/feature')(knex, eventStore); -const strategyDb = require('../../lib/db/strategy')(knex, eventStore); +const { + eventStore, + featureToggleStore, + strategyStore, + clientInstancesDb, + clientStrategiesDb, + clientMetricsDb, +} = require('../../lib/db')(knex); const app = require('../../app')({ baseUriPath: '', db: knex, - eventDb, eventStore, - featureDb, - strategyDb, + featureToggleStore, + strategyStore, clientStrategiesDb, clientInstancesDb, clientMetricsDb, @@ -42,7 +44,7 @@ function createStrategies () { emails: 'String', }, }, - ], strategy => strategyDb._createStrategy(strategy)); + ], strategy => strategyStore._createStrategy(strategy)); } function createFeatures () { @@ -106,7 +108,7 @@ function createFeatures () { }, }], }, - ], feature => featureDb._createFeature(feature)); + ], feature => featureToggleStore._createFeature(feature)); } function destroyStrategies () {