From d891628f7c866bfb4babbe8e542e14d9325d1fd2 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 14 May 2019 16:09:21 +0200 Subject: [PATCH] feat(migration): add support for first basic options on new schema Signed-off-by: Tobias Gurtzick --- lib/chain.js | 2 +- lib/executors/versioned/v2.js | 26 ++++++++++++++++---- lib/learn.js | 33 +++++++++++++++++++------ lib/methods/v2/statetravel.js | 5 +++- lib/methods/v2/translatestate.js | 42 ++++++++++++++++++++++++++++++++ lib/state.js | 37 ++++++++++++++++++++++------ lib/walker.js | 4 ++- 7 files changed, 125 insertions(+), 24 deletions(-) create mode 100644 lib/methods/v2/translatestate.js diff --git a/lib/chain.js b/lib/chain.js index fdda89ee..6e2fd402 100644 --- a/lib/chain.js +++ b/lib/chain.js @@ -74,7 +74,7 @@ class Chain { let ret; let stat = []; while (this.step()) { - ret = this._interface[m].apply(this._interface, args); + ret = await this._interface[m].apply(this._interface, args); stat.push(ret); if (this._step.hasStateUsage) { diff --git a/lib/executors/versioned/v2.js b/lib/executors/versioned/v2.js index 1b0d116c..08a0d63c 100644 --- a/lib/executors/versioned/v2.js +++ b/lib/executors/versioned/v2.js @@ -1,10 +1,12 @@ 'use strict'; const Promise = require('bluebird'); +const State = require('../../state'); const Learn = require('../../learn'); const Chain = require('../../chain'); -const TravelState = require('../../methods/v2/statetravel'); +const StateTravel = require('../../methods/v2/statetravel'); const Migrate = require('../../methods/v2/migrate'); +const TranslateState = require('../../methods/v2/translatestate'); const execUnit = { _extend: (context, type) => { @@ -39,18 +41,20 @@ const execUnit = { }); }, - up: function (context, driver, file) { + up: async function (context, driver, file) { const _file = file.get(); const chain = new Chain(context._driver, file, driver, context.internals); chain.addChain(Learn); - chain.addChain(TravelState); + chain.addChain(StateTravel); chain.addChain(Migrate); - return _file.migrate(chain, { + await State.startMigration(context._driver, file, context.internals); + await _file.migrate(chain, { options: context.internals.safeOptions, seedLink: context.seedLink, dbm: context.internals.safeOptions.dbmigrate }); + return Promise.promisify(context.writeMigrationRecord.bind(context))(file); return execUnit.learn(context, driver, file); return context.driver @@ -72,7 +76,19 @@ const execUnit = { .then(context.driver.endMigration.bind(context.driver)); }, - down: function (context, driver, file) { + down: async function (context, driver, file) { + await State.startMigration(context._driver, file, context.internals); + await TranslateState(context._driver, file, driver, context.internals); + await State.endMigration(context._driver, file, context.internals); + return Promise.promisify(context.deleteMigrationRecord.bind(context))(file); + + await _file.migrate(chain, { + options: context.internals.safeOptions, + seedLink: context.seedLink, + dbm: context.internals.safeOptions.dbmigrate + }); + return Promise.promisify(context.deleteMigrationRecord.bind(context))(file); + return driver .startMigration() .then(() => { diff --git a/lib/learn.js b/lib/learn.js index 8b323454..a0aa529c 100644 --- a/lib/learn.js +++ b/lib/learn.js @@ -9,6 +9,7 @@ class STD { this.modS = mod.c; this.modI = mod.i; this.modF = mod.f; + this.modC = mod.s; } dropTable (t) { @@ -33,6 +34,8 @@ class STD { delete this.indizies[t]; } + this.modC.push({ t: 1, a: 'createTable', c: [t] }); + return Promise.resolve(alter); } @@ -62,6 +65,8 @@ class STD { } }); + this.modC.push({ t: 0, a: 'dropTable', c: [t] }); + return Promise.resolve(); } @@ -71,6 +76,8 @@ class STD { delete this.schema[t]; } + this.modC.push({ t: 0, a: 'renameTable', c: [n, t] }); + return Promise.resolve(); } @@ -86,17 +93,16 @@ class STD { return this.createTable.apply(this, args); } - removeColumn (tableName, columnName, columnSpec) { + removeColumn (t, c) { let alter = {}; - alter = { c: {}, i: {}, f: {} }; - if (this.schema[tableName]) { - alter.c[tableName] = {}; - alter.c[tableName][columnName] = this.schema[tableName][columnName]; - this.modS[tableName] = {}; - this.modS[tableName][columnName] = this.schema[tableName][columnName]; - delete this.schema[tableName][columnName]; + if (this.schema[t]) { + this.modS[t] = {}; + this.modS[t][c] = this.schema[t][c]; + delete this.schema[t][c]; } + this.modC.push({ t: 1, a: 'addColumn', c: [t, c] }); + return Promise.resolve(alter); } @@ -106,6 +112,8 @@ class STD { delete this.schema[t][o]; } + this.modC.push({ t: 0, a: 'renameColumn', c: [t, n, o] }); + return Promise.resolve(); } @@ -116,6 +124,8 @@ class STD { this.schema[t] = this.schema[t] || {}; this.schema[t][c] = s; + this.modC.push({ t: 0, a: 'removeColumn', c: [t, c] }); + return Promise.resolve(); } @@ -132,8 +142,11 @@ class STD { changeColumn (t, c, s) { this.checkColumn(t, c); + this.modS[t][c] = this.schema[t][c]; this.schema[t][c] = Object.assign(this.schema[t][c], s); + this.modC.push({ t: 1, a: 'changeColumn', c: [t, c] }); + return Promise.resolve(); } @@ -153,6 +166,8 @@ class STD { if (!this.indizies[t]) this.indizies[t] = {}; this.indizies[t][i] = index; + this.modC.push({ t: 0, a: 'removeIndex', c: [t, i] }); + return Promise.resolve(); } @@ -201,6 +216,8 @@ class STD { this.foreign[t][k].r = r; } + this.modC.push({ t: 0, a: 'removeForeignKey', c: [t, k] }); + return Promise.resolve(); } diff --git a/lib/methods/v2/statetravel.js b/lib/methods/v2/statetravel.js index feaae90f..99cbccd8 100644 --- a/lib/methods/v2/statetravel.js +++ b/lib/methods/v2/statetravel.js @@ -30,12 +30,15 @@ class StateTravel { Object.keys(DEFAULT).forEach(m => { StateTravel.prototype[m] = async function (...args) { await State.step(this.driver, ++this._counter, this.internals); - return State.update( + const res = await State.update( this.driver, this.file, this.internals.modSchema, this.internals ); + + console.log('result', res); + return res; }; }); diff --git a/lib/methods/v2/translatestate.js b/lib/methods/v2/translatestate.js new file mode 100644 index 00000000..961de1fe --- /dev/null +++ b/lib/methods/v2/translatestate.js @@ -0,0 +1,42 @@ +const Promise = require('bluebird'); +const State = require('../../state'); + +const f = { + createTable: async (driver, [t], internals) => { + // console.log(t, internals.modSchema, internals.modSchema.c[t]); + return driver.createTable(t, internals.modSchema.c[t]); + } +}; + +async function processEntry ( + context, + file, + driver, + internals, + { t: type, a: action, c: args } +) { + // console.log('hello', type, action, args); + switch (type) { + case 0: + await driver[action].apply(driver, args); + break; + case 1: + await f[action](driver, args, internals); + break; + + default: + throw new Error(`Invalid state record, of type ${type}`); + } + + internals.modSchema.s.shift(); + await State.update(context, file, internals.modSchema, internals); +} +module.exports = async (context, file, driver, internals) => { + const mod = internals.modSchema; + + await Promise.resolve(mod.s).each(args => + processEntry(context, file, driver, internals, args) + ); + + await State.deleteState(context, file, internals); +}; diff --git a/lib/state.js b/lib/state.js index 6560b72e..8f7c369a 100644 --- a/lib/state.js +++ b/lib/state.js @@ -40,6 +40,11 @@ module.exports = { startMigration: async function (driver, file, internals) { let state = await driver._getKV(internals.migrationState, MSTATE); + let mig = await driver._getKV(internals.migrationState, file.name); + + if (mig) { + internals.modSchema = JSON.parse(mig.value); + } if (internals.dryRun) { return Promise.resolve(); @@ -47,21 +52,33 @@ module.exports = { await module.exports.lockState(driver, state, internals); - return driver._insertKV( - internals.migrationState, - file.name, - JSON.stringify({}) - ); + if (!mig) { + return driver._insertKV( + internals.migrationState, + file.name, + JSON.stringify({}) + ); + } else { + return Promise.resolve(); + } }, update: function (driver, file, state, internals) { - console.log('called'); + log.verbose(`[state] update state`); if (internals.dryRun) { - log.info(`[state] update state`); return Promise.resolve(); } + console.log('update', state); + + return driver._updateKV( + internals.migrationState, + file.name, + JSON.stringify(state) + ); + }, - return driver._updateKV(internals.migrationState, file.name, state); + get: function (driver, file, internals) { + return driver._getKV(internals.migrationState, file.name); }, tick: async function (driver, internals) { @@ -102,6 +119,10 @@ module.exports = { ); }, + deleteState: function (driver, file, internals) { + return driver._deleteKV(internals.migrationState, file.name); + }, + endMigration: async function (driver, file, internals) { if (internals.dryRun) { return Promise.resolve(); diff --git a/lib/walker.js b/lib/walker.js index 1ed572d8..2af28c08 100644 --- a/lib/walker.js +++ b/lib/walker.js @@ -31,7 +31,7 @@ const Walker = function (driver, directory, mode, intern, prefix) { this.directory = directory; this.internals = intern; this.internals.schema = { i: {}, c: {}, f: {} }; - this.internals.modSchema = { i: {}, c: {}, f: {} }; + this.internals.modSchema = { i: {}, c: {}, f: {}, s: [] }; this.mode = mode; if (!this.mode) this.prefix = `static-${prefix}`; @@ -173,6 +173,7 @@ Walker.prototype = { log.verbose(this.title + 'preparing to run up:', file.name); const _meta = file.get()._meta || {}; const version = _meta.version || 1; + this.internals.modSchema = { i: {}, c: {}, f: {}, s: [] }; return require(`./executors/versioned/v${version}`).up( this, this.driver, @@ -216,6 +217,7 @@ Walker.prototype = { log.verbose(this.title + 'preparing to run down:', file.name); const _meta = file.get()._meta || {}; const version = _meta.version || 1; + this.internals.modSchema = { i: {}, c: {}, f: {}, s: [] }; return require(`./executors/versioned/v${version}`).down( this, this.driver,