Skip to content

Commit 295431a

Browse files
committed
Asyncify mysql_db.js
1 parent 120cc91 commit 295431a

File tree

1 file changed

+111
-141
lines changed

1 file changed

+111
-141
lines changed

databases/mysql_db.js

+111-141
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18-
const async = require('async');
18+
const util = require('util');
1919

2020
exports.Database = function (settings) {
2121
// temp hack needs a proper fix..
@@ -50,6 +50,15 @@ exports.Database = function (settings) {
5050
this.settings.json = true;
5151
};
5252

53+
exports.Database.prototype._query = async function (...args) {
54+
return await new Promise((resolve, reject) => {
55+
this.db.query(...args, (err, ...args) => {
56+
if (err != null) return reject(err);
57+
resolve(args);
58+
});
59+
});
60+
};
61+
5362
exports.Database.prototype.clearPing = function () {
5463
if (this.interval) {
5564
clearInterval(this.interval);
@@ -68,6 +77,10 @@ exports.Database.prototype.schedulePing = function () {
6877
};
6978

7079
exports.Database.prototype.init = function (callback) {
80+
return util.callbackify(this._init.bind(this))(callback);
81+
};
82+
83+
exports.Database.prototype._init = async function () {
7184
const db = this.db;
7285

7386
const sqlCreate = `${'CREATE TABLE IF NOT EXISTS `store` ( ' +
@@ -78,105 +91,87 @@ exports.Database.prototype.init = function (callback) {
7891

7992
const sqlAlter = 'ALTER TABLE store MODIFY `key` VARCHAR(100) COLLATE utf8mb4_bin;';
8093

81-
db.query({
94+
await this._query({
8295
sql: sqlCreate,
8396
timeout: 60000,
84-
}, [], (err) => {
85-
// call the main callback
86-
callback(err);
87-
88-
// Checks for Database charset et al
89-
const dbCharSet =
90-
'SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME ' +
91-
`FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '${db.database}'`;
92-
db.query({
93-
sql: dbCharSet,
94-
timeout: 60000,
95-
}, (err, result) => {
96-
result = JSON.parse(JSON.stringify(result));
97-
if (result[0].DEFAULT_CHARACTER_SET_NAME !== db.charset) {
98-
console.error(`Database is not configured with charset ${db.charset} -- ` +
99-
'This may lead to crashes when certain characters are pasted in pads');
100-
console.log(result[0], db.charset);
101-
}
102-
103-
if (result[0].DEFAULT_COLLATION_NAME.indexOf(db.charset) === -1) {
104-
console.error(
105-
`Database is not configured with collation name that includes ${db.charset} -- ` +
106-
'This may lead to crashes when certain characters are pasted in pads');
107-
console.log(result[0], db.charset, result[0].DEFAULT_COLLATION_NAME);
108-
}
109-
});
97+
}, []);
98+
99+
// Checks for Database charset et al
100+
const dbCharSet =
101+
'SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME ' +
102+
`FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '${db.database}'`;
103+
let [result] = await this._query({
104+
sql: dbCharSet,
105+
timeout: 60000,
106+
});
110107

111-
const tableCharSet =
112-
'SELECT CCSA.character_set_name AS character_set_name ' +
113-
'FROM information_schema.`TABLES` ' +
114-
'T,information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA ' +
115-
'WHERE CCSA.collation_name = T.table_collation ' +
116-
`AND T.table_schema = '${db.database}' ` +
117-
"AND T.table_name = 'store'";
118-
db.query({
119-
sql: tableCharSet,
120-
timeout: 60000,
121-
}, (err, result, tf) => {
122-
if (!result[0]) {
123-
console.warn('Data has no character_set_name value -- ' +
124-
'This may lead to crashes when certain characters are pasted in pads');
125-
}
126-
if (result[0] && (result[0].character_set_name !== db.charset)) {
127-
console.error(`table is not configured with charset ${db.charset} -- ` +
128-
'This may lead to crashes when certain characters are pasted in pads');
129-
console.log(result[0], db.charset);
130-
}
131-
});
108+
result = JSON.parse(JSON.stringify(result));
109+
if (result[0].DEFAULT_CHARACTER_SET_NAME !== db.charset) {
110+
console.error(`Database is not configured with charset ${db.charset} -- ` +
111+
'This may lead to crashes when certain characters are pasted in pads');
112+
console.log(result[0], db.charset);
113+
}
132114

133-
// check migration level, alter if not migrated
134-
this.get('MYSQL_MIGRATION_LEVEL', (err, level) => {
135-
if (err) {
136-
throw err;
137-
}
138-
139-
if (level !== '1') {
140-
db.query({
141-
sql: sqlAlter,
142-
timeout: 60000,
143-
}, [], (err) => {
144-
if (err) {
145-
throw err;
146-
}
147-
148-
this.set('MYSQL_MIGRATION_LEVEL', '1', (err) => {
149-
if (err) {
150-
throw err;
151-
}
152-
});
153-
});
154-
}
155-
});
115+
if (result[0].DEFAULT_COLLATION_NAME.indexOf(db.charset) === -1) {
116+
console.error(
117+
`Database is not configured with collation name that includes ${db.charset} -- ` +
118+
'This may lead to crashes when certain characters are pasted in pads');
119+
console.log(result[0], db.charset, result[0].DEFAULT_COLLATION_NAME);
120+
}
121+
122+
const tableCharSet =
123+
'SELECT CCSA.character_set_name AS character_set_name ' +
124+
'FROM information_schema.`TABLES` ' +
125+
'T,information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA ' +
126+
'WHERE CCSA.collation_name = T.table_collation ' +
127+
`AND T.table_schema = '${db.database}' ` +
128+
"AND T.table_name = 'store'";
129+
[result] = await this._query({
130+
sql: tableCharSet,
131+
timeout: 60000,
156132
});
133+
if (!result[0]) {
134+
console.warn('Data has no character_set_name value -- ' +
135+
'This may lead to crashes when certain characters are pasted in pads');
136+
}
137+
if (result[0] && (result[0].character_set_name !== db.charset)) {
138+
console.error(`table is not configured with charset ${db.charset} -- ` +
139+
'This may lead to crashes when certain characters are pasted in pads');
140+
console.log(result[0], db.charset);
141+
}
142+
143+
// check migration level, alter if not migrated
144+
const level = await this._get('MYSQL_MIGRATION_LEVEL');
145+
146+
if (level !== '1') {
147+
await this._query({
148+
sql: sqlAlter,
149+
timeout: 60000,
150+
}, []);
151+
await this._set('MYSQL_MIGRATION_LEVEL', '1');
152+
}
157153

158154
this.schedulePing();
159155
};
160156

161157
exports.Database.prototype.get = function (key, callback) {
162-
this.db.query({
158+
return util.callbackify(this._get.bind(this))(key, callback);
159+
};
160+
161+
exports.Database.prototype._get = async function (key) {
162+
const [results] = await this._query({
163163
sql: 'SELECT `value` FROM `store` WHERE `key` = ? AND BINARY `key` = ?',
164164
timeout: 60000,
165-
}, [key, key],
166-
(err, results) => {
167-
let value = null;
168-
169-
if (!err && results.length === 1) {
170-
value = results[0].value;
171-
}
172-
173-
callback(err, value);
174-
});
175-
165+
}, [key, key]);
176166
this.schedulePing();
167+
return results.length === 1 ? results[0].value : null;
177168
};
178169

179170
exports.Database.prototype.findKeys = function (key, notKey, callback) {
171+
return util.callbackify(this._findKeys.bind(this))(key, notKey, callback);
172+
};
173+
174+
exports.Database.prototype._findKeys = async function (key, notKey) {
180175
let query = 'SELECT `key` FROM `store` WHERE `key` LIKE ?';
181176
const params = [];
182177

@@ -190,49 +185,44 @@ exports.Database.prototype.findKeys = function (key, notKey, callback) {
190185
query += ' AND `key` NOT LIKE ?';
191186
params.push(notKey);
192187
}
193-
this.db.query(
194-
{
195-
sql: query,
196-
timeout: 60000,
197-
}, params, (err, results) => {
198-
const value = [];
199-
200-
if (!err && results.length > 0) {
201-
results.forEach((val) => {
202-
value.push(val.key);
203-
});
204-
}
205-
206-
callback(err, value);
207-
});
208-
188+
const [results] = await this._query({
189+
sql: query,
190+
timeout: 60000,
191+
}, params);
209192
this.schedulePing();
193+
return results.map((val) => val.key);
210194
};
211195

212196
exports.Database.prototype.set = function (key, value, callback) {
213-
if (key.length > 100) {
214-
callback('Your Key can only be 100 chars');
215-
} else {
216-
this.db.query({
217-
sql: 'REPLACE INTO `store` VALUES (?,?)',
218-
timeout: 60000,
219-
}, [key, value], (err, info) => {
220-
callback(err);
221-
});
222-
}
197+
return util.callbackify(this._set.bind(this))(key, value, callback);
198+
};
223199

200+
exports.Database.prototype._set = async function (key, value) {
201+
if (key.length > 100) throw new Error('Your Key can only be 100 chars');
202+
await this._query({
203+
sql: 'REPLACE INTO `store` VALUES (?,?)',
204+
timeout: 60000,
205+
}, [key, value]);
224206
this.schedulePing();
225207
};
226208

227209
exports.Database.prototype.remove = function (key, callback) {
228-
this.db.query({
210+
return util.callbackify(this._remove.bind(this))(key, callback);
211+
};
212+
213+
exports.Database.prototype._remove = async function (key) {
214+
await this._query({
229215
sql: 'DELETE FROM `store` WHERE `key` = ? AND BINARY `key` = ?',
230216
timeout: 60000,
231-
}, [key, key], callback);
217+
}, [key, key]);
232218
this.schedulePing();
233219
};
234220

235221
exports.Database.prototype.doBulk = function (bulk, callback) {
222+
return util.callbackify(this._doBulk.bind(this))(bulk, callback);
223+
};
224+
225+
exports.Database.prototype._doBulk = async function (bulk) {
236226
let replaceSQL = 'REPLACE INTO `store` VALUES ';
237227

238228
// keysToDelete is a string of the form "(k1, k2, ..., kn)" painstakingly built by hand.
@@ -241,17 +231,17 @@ exports.Database.prototype.doBulk = function (bulk, callback) {
241231
let firstReplace = true;
242232
let firstRemove = true;
243233

244-
for (const i in bulk) {
245-
if (bulk[i].type === 'set') {
234+
for (const op of bulk) {
235+
if (op.type === 'set') {
246236
if (!firstReplace) replaceSQL += ',';
247237
firstReplace = false;
248238

249-
replaceSQL += `(${this.db.escape(bulk[i].key)}, ${this.db.escape(bulk[i].value)})`;
250-
} else if (bulk[i].type === 'remove') {
239+
replaceSQL += `(${this.db.escape(op.key)}, ${this.db.escape(op.value)})`;
240+
} else if (op.type === 'remove') {
251241
if (!firstRemove) keysToDelete += ',';
252242
firstRemove = false;
253243

254-
keysToDelete += this.db.escape(bulk[i].key);
244+
keysToDelete += this.db.escape(op.key);
255245
}
256246
}
257247

@@ -263,30 +253,10 @@ exports.Database.prototype.doBulk = function (bulk, callback) {
263253
`DELETE FROM \`store\` WHERE \`key\` IN ${keysToDelete} ` +
264254
`AND BINARY \`key\` IN ${keysToDelete};`;
265255

266-
async.parallel([
267-
(callback) => {
268-
if (!firstReplace) {
269-
this.db.query({
270-
sql: replaceSQL,
271-
timeout: 60000,
272-
},
273-
callback);
274-
} else {
275-
callback();
276-
}
277-
},
278-
(callback) => {
279-
if (!firstRemove) {
280-
this.db.query({
281-
sql: removeSQL,
282-
timeout: 60000,
283-
},
284-
callback);
285-
} else {
286-
callback();
287-
}
288-
},
289-
], callback);
256+
await Promise.all([
257+
firstReplace ? null : this._query({sql: replaceSQL, timeout: 60000}),
258+
firstRemove ? null : this._query({sql: removeSQL, timeout: 60000}),
259+
]);
290260

291261
this.schedulePing();
292262
};

0 commit comments

Comments
 (0)