Promisify and asyncify db initialization.

This commit is contained in:
baldo 2018-12-17 21:52:19 +01:00
parent 732c973145
commit ddb2f47a9d
2 changed files with 67 additions and 91 deletions

View file

@ -1,111 +1,83 @@
'use strict'; 'use strict';
var async = require('async'); const util = require('util');
var fs = require('graceful-fs'); const fs = require('graceful-fs');
var glob = require('glob'); const glob = util.promisify(require('glob'));
var path = require('path'); const path = require('path');
var config = require('../config'); const config = require('../config');
var Logger = require('../logger'); const Logger = require('../logger');
function applyPatch(db, file, callback) { async function applyPatch(db, file) {
Logger.tag('database', 'migration').info('Checking if patch need to be applied: %s', file); Logger.tag('database', 'migration').info('Checking if patch need to be applied: %s', file);
fs.readFile(file, function (err, contents) { const contents = await util.promisify(fs.readFile)(file);
if (err) { const version = path.basename(file, '.sql');
return callback(err);
}
var version = path.basename(file, '.sql'); const row = await db.get('SELECT * FROM schema_version WHERE version = ?', version);
if (row) {
// patch is already applied. skip!
Logger.tag('database', 'migration').info('Patch already applied, skipping: %s', file);
return
}
db.get('SELECT * FROM schema_version WHERE version = ?', version, function (err, row) { const sql = 'BEGIN TRANSACTION;\n' +
if (err) { contents.toString() + '\n' +
return callback(err); 'INSERT INTO schema_version (version) VALUES (\'' + version + '\');\n' +
} 'END TRANSACTION;';
if (row) { await db.exec(sql);
// patch is already applied. skip!
Logger.tag('database', 'migration').info('Patch already applied, skipping: %s', file);
return callback(null);
}
var sql = 'BEGIN TRANSACTION;\n' + Logger.tag('database', 'migration').info('Patch successfully applied: %s', file);
contents.toString() + '\n' +
'INSERT INTO schema_version (version) VALUES (\'' + version + '\');\n' +
'END TRANSACTION;';
db.exec(sql, function (err) {
if (err) {
return callback(err);
}
Logger.tag('database', 'migration').info('Patch successfully applied: %s', file);
callback(null);
});
});
});
} }
function applyMigrations(db, callback) { async function applyMigrations(db) {
Logger.tag('database', 'migration').info('Migrating database...'); Logger.tag('database', 'migration').info('Migrating database...');
var sql = 'BEGIN TRANSACTION; CREATE TABLE IF NOT EXISTS schema_version (\n' + const sql = 'BEGIN TRANSACTION; CREATE TABLE IF NOT EXISTS schema_version (\n' +
' version VARCHAR(255) PRIMARY KEY ASC,\n' + ' version VARCHAR(255) PRIMARY KEY ASC,\n' +
' applied_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL\n' + ' applied_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL\n' +
'); END TRANSACTION;'; '); END TRANSACTION;';
db.exec(sql, function (err) {
if (err) {
return callback(err);
}
glob(__dirname + '/patches/*.sql', function (err, files) { await db.exec(sql);
if (err) {
return callback(err);
}
async.eachSeries( const files = await glob(__dirname + '/patches/*.sql');
files, for (const file of files) {
function (file, fileCallback) { await applyPatch(db, file)
applyPatch(db, file, fileCallback); }
}, }
callback
); async function init() {
}); const SQLite3 = require('sqlite3');
const file = config.server.databaseFile;
Logger.tag('database').info('Setting up database: %s', file);
let db;
try {
db = new SQLite3.Database(file);
}
catch (error) {
Logger.tag('database').error('Error initialzing database:', error);
throw error;
}
db.on('profile', (sql, time) => Logger.tag('database').profile('[%sms]\t%s', time, sql));
try {
await applyMigrations(db);
}
catch (error) {
Logger.tag('database').error('Error migrating database:', error);
throw error;
}
// WARNING: We have to use funtion() syntax here, to satisfy ng-di. m(
return angular.module('ffffng').factory('Database', function () {
return db;
}); });
} }
module.exports = { module.exports = {
init: function (callback) { init
var SQLite3 = require('sqlite3');
var file = config.server.databaseFile;
Logger.tag('database').info('Setting up database: %s', file);
var db;
try {
db = new SQLite3.Database(file);
}
catch (error) {
Logger.tag('database').error('Error initialzing database:', error);
throw error;
}
db.on('profile', function (sql, time) {
Logger.tag('database').profile('[%sms]\t%s', time, sql);
});
applyMigrations(db, function (err) {
if (err) {
Logger.tag('database').error('Error migrating database:', err);
throw err;
}
angular.module('ffffng').factory('Database', function () {
return db;
});
callback();
});
}
}; };

View file

@ -9,8 +9,8 @@ angular.module('ffffng', []);
(function () { (function () {
// Use graceful-fs instead of fs also in all libraries to have more robust fs handling. // Use graceful-fs instead of fs also in all libraries to have more robust fs handling.
var realFs = require('fs'); const realFs = require('fs');
var gracefulFs = require('graceful-fs'); const gracefulFs = require('graceful-fs');
gracefulFs.gracefulify(realFs); gracefulFs.gracefulify(realFs);
})(); })();
@ -46,9 +46,10 @@ require('./validation/validator');
require('./jobs/scheduler'); require('./jobs/scheduler');
var db = require('./db/database'); const db = require('./db/database');
db.init(function () { db.init().then(() => {
// WARNING: We have to use funtion() syntax here, to satisfy ng-di. m(
angular.injector(['ffffng']).invoke(function (config, app, Logger, Scheduler, Router) { angular.injector(['ffffng']).invoke(function (config, app, Logger, Scheduler, Router) {
Logger.tag('main').info('Initializing...'); Logger.tag('main').info('Initializing...');
@ -58,4 +59,7 @@ db.init(function () {
app.listen(config.server.port, '::'); app.listen(config.server.port, '::');
module.exports = app; module.exports = app;
}); });
}).catch(error => {
console.error('Could not init database: ', error);
process.exit(1);
}); });