Skip to content

Commit

Permalink
Ping knex connections on server init. Closes #15
Browse files Browse the repository at this point in the history
  • Loading branch information
devinivy committed Jan 18, 2017
1 parent fdd13f5 commit 847a1ed
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 10 deletions.
62 changes: 52 additions & 10 deletions lib/index.js
Expand Up @@ -110,13 +110,51 @@ internals.initialize = (server, next) => {
});
});

if (!collector.migrateOnStart) {
return next();
}
const knexes = internals.getKnexes(collector.knexGroups);
const ping = (knex, cb) => {

return knex.queryBuilder().select(knex.raw('1')).asCallback((err) => {

if (err) {
const models = collector.models;
const modelNames = Object.keys(models).filter((name) => {

return models[name].knex() === knex;
});

// Augment original error message

const quoted = (x) => `"${x}"`;

let message = 'Could not connect to database using schwifty knex instance';
message += modelNames.length ? ` for models: ${modelNames.map(quoted).join(', ')}.` : '.';
err.message = (message + (err.message ? ': ' + err.message : ''));

return cb(err);
};

return cb();
});
};

// Ping each knex connection

const rollback = (collector.migrateOnStart === 'rollback');
Items.parallel(knexes, ping, (err) => {

Migrator.migrate(collector.knexGroups, rootKnex, rollback, next);
if (err) {
return next(err);
}

// Maybe run migrations

if (!collector.migrateOnStart) {
return next();
}

const rollback = (collector.migrateOnStart === 'rollback');

Migrator.migrate(collector.knexGroups, rootKnex, rollback, next);
});
};

internals.schwifty = function (config) {
Expand Down Expand Up @@ -229,15 +267,19 @@ internals.stop = function (server, next) {
return next();
}

let knexes = collector.knexGroups
.map((knexGroup) => knexGroup.knex)
.filter((maybeKnex) => !!maybeKnex);

knexes = internals.uniqueObjects(knexes);
const knexes = internals.getKnexes(collector.knexGroups);

Items.parallel(knexes, (knex, nxt) => knex.destroy(nxt), next);
};

internals.getKnexes = (knexGroups) => {

const knexes = knexGroups.map((knexGroup) => knexGroup.knex)
.filter((maybeKnex) => !!maybeKnex);

return internals.uniqueObjects(knexes);
};

// Dedupes an array of objects
internals.uniqueObjects = (arr) => {

Expand Down
135 changes: 135 additions & 0 deletions test/index.js
Expand Up @@ -953,6 +953,141 @@ describe('Schwifty', () => {
});
});
});

describe('bails when a knex instance is not pingable', () => {

const failKnexWith = (knex, error) => {

knex.queryBuilder = () => ({
select: () => ({
asCallback: (cb) => cb(error)
})
});

return knex;
};

it('and lists associated models in error.', (done) => {

const knex = failKnexWith(makeKnex(), new Error());

getServer({ knex, models: [TestModels.Dog] }, (err, server) => {

expect(err).to.not.exist();

const plugin = (srv, opts, next) => {

srv.schwifty(TestModels.Person);
next();
};

plugin.attributes = { name: 'plugin' };

server.register(plugin, (err) => {

expect(err).to.not.exist();

server.initialize((err) => {

expect(err).to.exist();
expect(err.message).to.startWith('Could not connect to database using schwifty knex instance for models: "Dog", "Person".');

done();
});
});
});
});

it('and doesn\'t list associated models in error when there are none.', (done) => {

const knex = failKnexWith(makeKnex(), new Error());

getServer({ knex }, (err, server) => {

expect(err).to.not.exist();

server.initialize((err) => {

expect(err).to.exist();
expect(err.message).to.startWith('Could not connect to database using schwifty knex instance.');

done();
});
});
});

it('and augments the original error\'s message.', (done) => {

const error = new Error('Also this other thing went wrong.');
const knex = failKnexWith(makeKnex(), error);

getServer({ knex }, (err, server) => {

expect(err).to.not.exist();

server.initialize((err) => {

expect(err).to.exist();
expect(err).to.shallow.equal(error);
expect(err.message).to.equal('Could not connect to database using schwifty knex instance.: Also this other thing went wrong.');

done();
});
});
});

it('and adds a message to the original error if it did not already have one.', (done) => {

const error = new Error();
const knex = failKnexWith(makeKnex(), error);

getServer({ knex }, (err, server) => {

expect(err).to.not.exist();

server.initialize((err) => {

expect(err).to.exist();
expect(err).to.shallow.equal(error);
expect(err.message).to.equal('Could not connect to database using schwifty knex instance.');

done();
});
});
});

it('and only requires one not be pingable to fail.', (done) => {

getServer({ knex: makeKnex() }, (err, server) => {

expect(err).to.not.exist();

const error = new Error();
const knex = failKnexWith(makeKnex(), error);

const plugin = (srv, opts, next) => {

srv.schwifty({ knex });
next();
};

plugin.attributes = { name: 'plugin' };

server.register(plugin, (err) => {

expect(err).to.not.exist();

server.initialize((err) => {

expect(err).to.exist();
expect(err).to.shallow.equal(error);

done();
});
});
});
});
});
});

describe('migrations', () => {
Expand Down

0 comments on commit 847a1ed

Please sign in to comment.