efcsydney/efcsydney-roster

View on GitHub
api/utilities/database-util.js

Summary

Maintainability
B
5 hrs
Test Coverage
const fs = require('fs');
const moment = require('moment');
const env = process.env.NODE_ENV || 'development';
const dbConfig = require(__dirname + '/../../config/database.json')[env];
const { exec } = require('child_process');
const log = require('./logger');
const config = require('config');

const BACKUP_DIR = config.get('databaseBackup.backupDirectory');

function getCurrentDateString() {
  return moment().format('YYYYMMDD');
}

function getLastMonthString() {
  return moment()
    .subtract(30, 'days')
    .format('YYYYMMDD');
}

function getBackupFileName(date) {
  return `${dbConfig.database}_${date}.sql`;
}

function getRestoreFileName(dateString) {
  return `${dbConfig.database}_${dateString}.sql`;
}

function ensurePathExists(path) {
  if (!fs.existsSync(path)) {
    fs.mkdirSync(path);
  }
}

// The command has to be in single line only. Multi-line interpolated string is seperated by
// carriage return and will cause the command fails to execute on the shell.
function getBackupQuery(filename) {
  return `mysqldump -u ${dbConfig.username} -p "${dbConfig.password}" -h ${
    dbConfig.host
  } ${dbConfig.database} > ${BACKUP_DIR}/${filename}`;
}

function getRestoreQuery(filename) {
  return `mysql -u ${dbConfig.username} -p "${dbConfig.password}" -h ${
    dbConfig.host
  } ${dbConfig.database} < ${BACKUP_DIR}/${filename}`;
}

function getFileRotation(filename) {
  return `rm -f ${BACKUP_DIR}/${filename}`;
}

function backupDatabase() {
  const backupFileName = getBackupFileName(getCurrentDateString());
  const removeFileName = getBackupFileName(getLastMonthString());
  ensurePathExists(BACKUP_DIR);

  log.info(
    `[BEGIN] DatabaseUtil#backupDatabase; file: ${backupFileName}, at: ${moment()}`
  );

  exec(getBackupQuery(backupFileName), function(err) {
    if (err) {
      log.error(`[ERROR] DatabaseUtil#backupDatabase; reason: ${err.message}`);
    } else {
      log.info(
        `[END] DatabaseUtil#backupDatabase; Create file: ${backupFileName}, at: ${moment()}`
      );
    }
  });

  exec(getFileRotation(removeFileName), function(err) {
    if (err) {
      log.error(`[ERROR] DatabaseUtil#backupDatabase; reason: ${err.message}`);
    } else {
      log.info(
        `[END] DatabaseUtil#backupDatabase; Remove file: ${removeFileName}, at: ${moment()}`
      );
    }
  });
}

function restoreDatabase(dateString) {
  const restoreFileName = getRestoreFileName(dateString);

  log.info(
    `[BEGIN] DatabaseUtil#restoreDatabase; file: ${restoreFileName}, at: ${moment()}`
  );
  log.info(getRestoreQuery(restoreFileName));

  exec(getRestoreQuery(restoreFileName), function(err, stdout, stderr) {
    if (err || stderr) {
      log.error(
        `[ERROR] DatabaseUtil#restoreDatabase; reason: ${err.message ||
          stderr.message}`
      );
    }

    if (stdout) {
      log.info(
        `[END] DatabaseUtil#restoreDatabase; file: ${restoreFileName}, at: ${moment()}`
      );
    }
  });
}

module.exports = {
  backupDatabase,
  restoreDatabase
};