db-migrate 1.0.0-beta.26 → 1.0.0-beta.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/connect.js CHANGED
@@ -9,7 +9,9 @@ var path = require('path');
9
9
  var log = require('db-migrate-shared').log;
10
10
  const Promise = require('bluebird');
11
11
 
12
- exports.connect = function (config, PassedClass) {
12
+ Promise.promisifyAll(driver);
13
+
14
+ exports.connect = async function (config, PassedClass) {
13
15
  var internals = {};
14
16
  var prefix = 'migration';
15
17
  if (config.config) {
@@ -18,6 +20,8 @@ exports.connect = function (config, PassedClass) {
18
20
  config = config.config;
19
21
  }
20
22
 
23
+ const db2 = await driver.connectAsync(config, internals);
24
+
21
25
  return Promise.fromCallback(callback => {
22
26
  driver.connect(config, internals, function (err, db) {
23
27
  if (err) {
@@ -25,6 +29,14 @@ exports.connect = function (config, PassedClass) {
25
29
  return;
26
30
  }
27
31
 
32
+ const realClose = db.close;
33
+ // close both lines with one disconnect action
34
+ db.close = function (cb) {
35
+ db2.close(function () {});
36
+ db.close = realClose;
37
+ db.close(cb);
38
+ };
39
+
28
40
  var dirPath = path.resolve(
29
41
  internals.argv['migrations-dir'] || 'migrations'
30
42
  );
@@ -59,7 +71,8 @@ exports.connect = function (config, PassedClass) {
59
71
  dirPath,
60
72
  internals.mode !== 'static',
61
73
  internals,
62
- prefix
74
+ prefix,
75
+ { db2 }
63
76
  )
64
77
  );
65
78
  });
@@ -100,6 +113,7 @@ exports.connect = function (config, PassedClass) {
100
113
  db,
101
114
  oldClose,
102
115
  prefix,
116
+ db2,
103
117
  cb
104
118
  );
105
119
  };
@@ -115,7 +129,8 @@ exports.connect = function (config, PassedClass) {
115
129
  dirPath,
116
130
  internals.mode !== 'static',
117
131
  internals,
118
- prefix
132
+ prefix,
133
+ { db2 }
119
134
  )
120
135
  );
121
136
  }
@@ -142,6 +157,7 @@ function migrationFiles (
142
157
  db,
143
158
  close,
144
159
  prefix,
160
+ db2,
145
161
  cb
146
162
  ) {
147
163
  var file;
@@ -187,7 +203,8 @@ function migrationFiles (
187
203
  internals.argv['migrations-dir'],
188
204
  internals.mode !== 'static',
189
205
  internals,
190
- prefix
206
+ prefix,
207
+ { db2 }
191
208
  )
192
209
  );
193
210
 
package/lib/chain.js CHANGED
@@ -55,10 +55,11 @@ const dbmControl = {
55
55
  };
56
56
 
57
57
  class Chain {
58
- constructor (context, file, driver, internals) {
58
+ constructor (context, file, driver, internals, pdriver) {
59
59
  this.file = file;
60
60
  this.context = context;
61
61
  this.driver = context;
62
+ this.pdriver = pdriver;
62
63
  this.udriver = driver;
63
64
  if (this.udriver._dbmControl !== true) {
64
65
  this.udriver._counter = dbmControl;
@@ -113,7 +114,8 @@ class Chain {
113
114
  this.context,
114
115
  this.file,
115
116
  this.udriver,
116
- this.internals
117
+ this.internals,
118
+ this.pdriver
117
119
  );
118
120
  }
119
121
 
@@ -136,6 +138,7 @@ class Chain {
136
138
  this._step.useState(ret);
137
139
  }
138
140
 
141
+ // need to check if we still want this
139
142
  if (this._step.hasModification) {
140
143
  const ret = this._step.modify(
141
144
  this.context,
@@ -29,7 +29,7 @@ const execUnit = {
29
29
 
30
30
  up: async function (context, driver, file) {
31
31
  const _file = file.get();
32
- const chain = new Chain(context._driver, file, driver, context.internals);
32
+ const chain = new Chain(context._driver, file, driver, context.internals, context._pdriver);
33
33
  if (!_file._meta.noDefaultColumn) {
34
34
  chain.addChain(AddConventions);
35
35
  }
@@ -37,7 +37,7 @@ const execUnit = {
37
37
  chain.addChain(StateTravel);
38
38
  chain.addChain(Migrate);
39
39
 
40
- await State.startMigration(context._driver, file, context.internals);
40
+ await State.startMigration(context._pdriver, file, context.internals);
41
41
  // startMigration - needs secondary instance since we can not afford to
42
42
  // loose state and the transaction start will include these for roll back
43
43
  // we will disable them probably at all from DDL when the driver does not
@@ -62,20 +62,20 @@ const execUnit = {
62
62
  throw err;
63
63
  }
64
64
  await Promise.promisify(context.writeMigrationRecord.bind(context))(file);
65
- return State.endMigration(context._driver, file, context.internals);
65
+ return State.endMigration(context._pdriver, file, context.internals);
66
66
  // end migration, same as start migration
67
67
  },
68
68
 
69
69
  fix: async function (context, driver, file) {
70
70
  const _file = file.get();
71
- const chain = new Chain(context._driver, file, driver, context.internals);
71
+ const chain = new Chain(context._driver, file, driver, context.internals, context._pdriver);
72
72
  if (!_file._meta.noDefaultColumn) {
73
73
  chain.addChain(AddConventions);
74
74
  }
75
75
  chain.addChain(Learn);
76
- // chain.addChain(StateTravel);
76
+ chain.addChain(StateTravel);
77
77
 
78
- await State.startMigration(context._driver, file, context.internals);
78
+ await State.startMigration(context._pdriver, file, context.internals);
79
79
  // startMigration - needs secondary instance since we can not afford to
80
80
  // loose state and the transaction start will include these for roll back
81
81
  // we will disable them probably at all from DDL when the driver does not
@@ -99,17 +99,16 @@ const execUnit = {
99
99
  await execUnit.down(context, driver, file);
100
100
  throw err;
101
101
  }
102
- await Promise.promisify(context.writeMigrationRecord.bind(context))(file);
103
- await State.endMigration(context._driver, file, context.internals);
102
+ await State.endMigration(context._pdriver, file, context.internals);
104
103
  log.verbose(`[fix] current schema`, util.inspect(context.internals.schema, false, null, true));
105
104
  // end migration, same as start migration
106
105
  },
107
106
 
108
107
  down: async function (context, driver, file) {
109
108
  // start migration, see up comments
110
- await State.startMigration(context._driver, file, context.internals);
111
- await TranslateState(context._driver, file, driver, context.internals);
112
- await State.endMigration(context._driver, file, context.internals);
109
+ await State.startMigration(context._pdriver, file, context.internals);
110
+ await TranslateState(context._driver, file, driver, context.internals, context._pdriver);
111
+ await State.endMigration(context._pdriver, file, context.internals);
113
112
  return Promise.promisify(context.deleteMigrationRecord.bind(context))(file);
114
113
  // end migration, see up comments
115
114
  }
@@ -18,16 +18,17 @@ const DEFAULT = {
18
18
  };
19
19
 
20
20
  class StateTravel {
21
- constructor (internals, file, driver) {
21
+ constructor (internals, file, driver, pdriver) {
22
22
  this.file = file;
23
23
  this.internals = internals;
24
24
  this.driver = driver;
25
+ this.pdriver = pdriver;
25
26
  this._counter = 0;
26
27
  this._default = async function _default () {
27
- await State.step(this.driver, ++this._counter, this.internals);
28
+ await State.step(this.pdriver, ++this._counter, this.internals);
28
29
 
29
30
  return State.update(
30
- this.driver,
31
+ this.pdriver,
31
32
  this.file,
32
33
  this.internals.modSchema,
33
34
  this.internals
@@ -49,9 +50,9 @@ const noTravelError = prop => {
49
50
  };
50
51
 
51
52
  module.exports = {
52
- getInterface: (context, file, driver, internals) => {
53
+ getInterface: (context, file, driver, internals, pdriver) => {
53
54
  if (context.learnable) {
54
- const st = new StateTravel(internals, file, context);
55
+ const st = new StateTravel(internals, file, context, pdriver);
55
56
  return Shadow.overshadow(
56
57
  driver,
57
58
  Object.assign(st, context.statechanger),
@@ -72,6 +72,7 @@ async function processEntry (
72
72
  file,
73
73
  driver,
74
74
  internals,
75
+ pdriver,
75
76
  { t: type, a: action, c: args }
76
77
  ) {
77
78
  let skip = false;
@@ -79,7 +80,7 @@ async function processEntry (
79
80
  if (
80
81
  internals.rollback === true &&
81
82
  internals.rollbackContinue !== true &&
82
- driver.udriver._meta.signalColumns.indexOf(action) !== -1
83
+ driver.udriver._meta?.signalColumns?.indexOf(action) !== -1
83
84
  ) {
84
85
  internals.rollbackContinue = true;
85
86
  skip = driver.udriver._counter.previousSignal() === null;
@@ -101,20 +102,20 @@ async function processEntry (
101
102
  }
102
103
 
103
104
  internals.modSchema.s.shift();
104
- await State.update(context, file, internals.modSchema, internals);
105
+ await State.update(pdriver, file, internals.modSchema, internals);
105
106
  }
106
107
 
107
- module.exports = async (context, file, driver, internals) => {
108
+ module.exports = async (context, file, driver, internals, pdriver) => {
108
109
  const mod = internals.modSchema;
109
110
 
110
- const chain = new Chain(context, file, driver, internals);
111
+ const chain = new Chain(context, file, driver, internals, pdriver);
111
112
  internals.unlearn = true;
112
113
 
113
114
  chain.addChain(Learn);
114
115
  chain.addChain(Migrate);
115
116
  await Promise.resolve(mod.s.reverse()).each(args =>
116
- processEntry(context, file, chain, internals, args)
117
+ processEntry(context, file, chain, internals, pdriver, args)
117
118
  );
118
119
 
119
- await State.deleteState(context, file, internals);
120
+ await State.deleteState(pdriver, file, internals);
120
121
  };
package/lib/state.js CHANGED
@@ -1,12 +1,25 @@
1
1
  const MSTATE = '__dbmigrate_state__';
2
2
  const SSTATE = '__dbmigrate_schema__';
3
+ const RUNON = 'run_on';
4
+
3
5
  const log = require('db-migrate-shared').log;
4
6
  const fs = require('fs').promises;
5
7
  const path = require('path');
8
+ const crypto = require('crypto');
9
+
10
+ const ID = crypto.randomBytes(32).toString('base64');
11
+ let owner = false;
6
12
 
7
13
  module.exports = {
14
+ /**
15
+ * Lock state will add the basic state controller an ID
16
+ * and a process controlled date.
17
+ * It is important that all systems are in sync. We will use the
18
+ * database clock instead if possible.
19
+ */
8
20
  lockState: async function (driver, state, internals) {
9
21
  if (!state) {
22
+ owner = true;
10
23
  return driver._insertKV(
11
24
  internals.migrationState,
12
25
  MSTATE,
@@ -14,23 +27,48 @@ module.exports = {
14
27
  s: {
15
28
  step: 0,
16
29
  fin: 0,
30
+ ID,
17
31
  date: new Date()
18
32
  }
19
33
  })
20
34
  );
21
35
  } else {
36
+ let runOn = state.run_on;
22
37
  state = state.value;
23
38
  state = JSON.parse(state);
24
- state.s.date = new Date();
25
- return driver._updateKV(
39
+
40
+ if (!state.s.ID || state.s.ID !== ID) {
41
+ owner = true;
42
+ state.s.ID = ID;
43
+ }
44
+
45
+ const d = new Date();
46
+
47
+ state.s.date = d;
48
+ await driver._updateKVC(
26
49
  internals.migrationState,
27
50
  MSTATE,
28
-
29
- JSON.stringify(state)
51
+ JSON.stringify(state),
52
+ RUNON,
53
+ runOn
30
54
  );
55
+
56
+ state = await driver._getKV(internals.migrationState, MSTATE);
57
+
58
+ runOn = state.run_on;
59
+ state = state.value;
60
+ state = JSON.parse(state);
61
+
62
+ if (state.s.ID !== ID) {
63
+ owner = false;
64
+ }
31
65
  }
32
66
  },
33
67
 
68
+ isOwner: function () {
69
+ return owner;
70
+ },
71
+
34
72
  init: async function (driver, internals, { emptyState, backupState }) {
35
73
  await driver._createKV(internals.migrationState);
36
74
  const _schema = await driver._getKV(internals.migrationState, SSTATE);
@@ -47,6 +85,7 @@ module.exports = {
47
85
 
48
86
  log.info(`[state] Created a backup of ${internals.migrationState} by renaming table to ${newName}`);
49
87
  await driver._createKV(internals.migrationState);
88
+ await driver._insertKV(internals.migrationState, SSTATE, '{}');
50
89
  }
51
90
  }
52
91
 
@@ -96,7 +135,7 @@ module.exports = {
96
135
  return Promise.resolve();
97
136
  }
98
137
 
99
- await driver._updateKV(internals.migrationState, SSTATE, internals.schema);
138
+ await driver._updateKV(internals.migrationState, SSTATE, JSON.stringify(internals.schema));
100
139
 
101
140
  return driver._updateKV(
102
141
  internals.migrationState,
@@ -114,17 +153,40 @@ module.exports = {
114
153
  return Promise.resolve();
115
154
  }
116
155
 
117
- let { value: state } = await driver._getKV(
156
+ let state = await driver._getKV(
118
157
  internals.migrationState,
119
158
  MSTATE
120
159
  );
160
+
161
+ let runOn = state.run_on;
162
+ state = state.value;
121
163
  state = JSON.parse(state);
122
- state.s.date = new Date();
123
- return driver._updateKV(
164
+
165
+ if (!state.s.ID || state.s.ID !== ID) {
166
+ owner = true;
167
+ state.s.ID = ID;
168
+ }
169
+
170
+ const d = new Date();
171
+
172
+ state.s.date = d;
173
+ await driver._updateKVC(
124
174
  internals.migrationState,
125
175
  MSTATE,
126
- JSON.stringify(state)
176
+ JSON.stringify(state),
177
+ RUNON,
178
+ runOn
127
179
  );
180
+
181
+ state = await driver._getKV(internals.migrationState, MSTATE);
182
+
183
+ runOn = state.run_on;
184
+ state = state.value;
185
+ state = JSON.parse(state);
186
+
187
+ if (state.s.ID !== ID) {
188
+ owner = false;
189
+ }
128
190
  },
129
191
 
130
192
  step: async function (driver, step, internals) {
@@ -164,6 +226,9 @@ module.exports = {
164
226
  state.s.date = new Date();
165
227
  state.s.fin = 1;
166
228
 
229
+ // unlock from current process
230
+ state.s.ID = 0;
231
+
167
232
  return driver._updateKV(
168
233
  internals.migrationState,
169
234
  MSTATE,
package/lib/walker.js CHANGED
@@ -24,10 +24,12 @@ const INTERFACES = {
24
24
  'static-seed': require('./interface/seederInterface.js')
25
25
  };
26
26
 
27
- const Walker = function (driver, directory, mode, intern, prefix) {
27
+ const Walker = function (driver, directory, mode, intern, prefix, opts = {}) {
28
28
  this.driver = dbmUtil.reduceToInterface(driver, INTERFACES[prefix]);
29
29
  this._driver = driver;
30
+ this._pdriver = opts.db2;
30
31
  Promise.promisifyAll(this._driver);
32
+ Promise.promisifyAll(this._pdriver);
31
33
  this.directory = directory;
32
34
  this.internals = intern;
33
35
  /**
@@ -60,11 +62,11 @@ const Walker = function (driver, directory, mode, intern, prefix) {
60
62
 
61
63
  Walker.prototype = {
62
64
  createTables: async function (options) {
63
- await State.init(this._driver, this.internals, options);
65
+ await State.init(this._pdriver, this.internals, options);
64
66
  return this._driver._createList(this.internals.migrationTable);
65
67
  },
66
68
 
67
- createMigrationsTable: function (options) {
69
+ createMigrationsTable: function (options = {}) {
68
70
  if (
69
71
  typeof this._driver._createList !== 'function' ||
70
72
  typeof this._driver._getList !== 'function' ||
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "db-migrate",
3
3
  "description": "Database migration framework for node.js",
4
- "author": "Tobias Gurtick",
4
+ "author": "Tobias Gurtzick",
5
5
  "bin": "./bin/db-migrate",
6
6
  "keywords": [
7
7
  "database",
@@ -31,7 +31,7 @@
31
31
  "programable",
32
32
  "api"
33
33
  ],
34
- "version": "1.0.0-beta.26",
34
+ "version": "1.0.0-beta.28",
35
35
  "engines": {
36
36
  "node": ">=8.0.0"
37
37
  },
package/tttt.js ADDED
@@ -0,0 +1,2 @@
1
+
2
+