Skip to content

Commit

Permalink
quick-and-dirty DROP backoff loop (closes #42)
Browse files Browse the repository at this point in the history
  • Loading branch information
sastraxi committed Jun 2, 2019
1 parent 3f9d21d commit 34fdf95
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 2 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -15,6 +15,7 @@
},
"dependencies": {
"ansi-colors": "^3.2.3",
"backoff": "^2.5.0",
"bluebird": "^3.5.3",
"cli-table": "^0.3.1",
"debug": "^4.1.1",
Expand Down
59 changes: 57 additions & 2 deletions src/cmd/destroy.js
@@ -1,4 +1,6 @@
const backoff = require('backoff');
const confirm = require('../util/confirm-prompt');
const connectionCountTask = require('../task/connection-count');

exports.command = ['destroy <target>', 'drop'];
exports.desc = 'Destroys the given database. This cannot be undone!';
Expand All @@ -9,9 +11,55 @@ exports.builder = yargs =>
describe: 'The database to drop. You can maintain a blacklist '
+ 'of databases to protect from this command in your .pgshrc',
type: 'string',
})
.option('f', {
alias: 'fail-fast',
type: 'boolean',
describe: 'Do not wait for the database to be unused; exit immediately',
default: false,
});

exports.handler = async ({ target }) => {
const fibonacciBackoff = backoff.fibonacci({
randomisationFactor: 0,
initialDelay: 300,
maxDelay: 12000,
});

const waitFor = (db, target, interruptHandler, failFast) =>
new Promise(async (resolve) => {
const connectionCount = connectionCountTask(db);
const otherConnections = await connectionCount(target);
const isPlural = otherConnections !== 1;

if (otherConnections === 0) {
return resolve();
}

console.log(
`There ${isPlural ? 'are' : 'is'} ${otherConnections} other session${isPlural ? 's' : ''}`,
`using the database.${failFast ? '' : ' (waiting)'}`,
);

if (failFast) {
return interruptHandler();
}

const readyHandler = async () => {
if (await connectionCount(target) > 0) {
fibonacciBackoff.backoff();
} else {
process.removeListener('SIGINT', interruptHandler);
fibonacciBackoff.removeListener('ready', readyHandler);
fibonacciBackoff.reset();
resolve();
}
};
process.on('SIGINT', interruptHandler);
fibonacciBackoff.on('ready', readyHandler);
return fibonacciBackoff.backoff();
});

exports.handler = async ({ target, failFast }) => {
const db = require('../db')();

const current = db.thisDb();
Expand All @@ -33,8 +81,15 @@ exports.handler = async ({ target }) => {
return process.exit(3);
}

const interruptHandler = () => {
console.log(`\nDid not drop ${target}!`);
return process.exit(0);
};

try {
await waitFor(db, target, interruptHandler, failFast);
await confirm('Type the database name to drop it: ', target);
await waitFor(db, target, interruptHandler, failFast);
} catch (err) {
console.log('Not dropping.');
return process.exit(0);
Expand All @@ -48,6 +103,6 @@ exports.handler = async ({ target }) => {
} catch (err) {
console.error(`Could not drop ${target}!`);
console.error(err);
return process.exit(3);
return process.exit(4);
}
};
18 changes: 18 additions & 0 deletions src/task/connection-count.js
@@ -0,0 +1,18 @@
/**
* Returns the number of connections to the given database,
* without counting this one (if we're connecting to the same db).
*/
module.exports = db => async (databaseName) => {
const knex = db.connectAsSuper();

const numConnections = await knex.raw(`
select count(*) as connections
from pg_stat_activity
where datname = ?
`, [databaseName])
.then(({ rows }) => +rows[0].connections);

return db.thisDb() === databaseName
? numConnections - 1
: numConnections;
};
12 changes: 12 additions & 0 deletions yarn.lock
Expand Up @@ -385,6 +385,13 @@ babel-preset-jest@^24.1.0:
"@babel/plugin-syntax-object-rest-spread" "^7.0.0"
babel-plugin-jest-hoist "^24.1.0"

backoff@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f"
integrity sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=
dependencies:
precond "0.2"

balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
Expand Down Expand Up @@ -3272,6 +3279,11 @@ postgres-interval@^1.1.0:
dependencies:
xtend "^4.0.0"

precond@0.2:
version "0.2.3"
resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac"
integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=

prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
Expand Down

0 comments on commit 34fdf95

Please sign in to comment.