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 +21 -4
- package/lib/chain.js +5 -2
- package/lib/executors/versioned/v2.js +10 -11
- package/lib/methods/v2/statetravel.js +6 -5
- package/lib/methods/v2/translatestate.js +7 -6
- package/lib/state.js +74 -9
- package/lib/walker.js +5 -3
- package/package.json +2 -2
- package/tttt.js +2 -0
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
76
|
+
chain.addChain(StateTravel);
|
|
77
77
|
|
|
78
|
-
await State.startMigration(context.
|
|
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
|
|
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.
|
|
111
|
-
await TranslateState(context._driver, file, driver, context.internals);
|
|
112
|
-
await State.endMigration(context.
|
|
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.
|
|
28
|
+
await State.step(this.pdriver, ++this._counter, this.internals);
|
|
28
29
|
|
|
29
30
|
return State.update(
|
|
30
|
-
this.
|
|
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
|
|
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(
|
|
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(
|
|
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
|
-
|
|
25
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
123
|
-
|
|
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.
|
|
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
|
|
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.
|
|
34
|
+
"version": "1.0.0-beta.28",
|
|
35
35
|
"engines": {
|
|
36
36
|
"node": ">=8.0.0"
|
|
37
37
|
},
|
package/tttt.js
ADDED