Sunday, January 17, 2021

Node.js exec with promisify

I'm working on a project where Nodejs is used for the backend and redis is used for caching application data.  Here's an example of making a shell command to delete redis cache keys using child_process exec and promisify.  I find it easier (and more intuitive) to use async/await than to use callbacks.

Environment:
CentOS Linux release 7.3.1611 (Core)
node v14.9.0

// child process currently doesn't natively support promises, however can wrap the
// methods with promises using built-in promisify util
const { promisify } = require("util");
const execAsync = promisify(require("child_process").exec);

/**
 * Deletes all keys from cache that start with cacheCode param.  If
 * cacheCode is not defined, deletes all cache.
 * @param {String} cacheCode.
 * @throws {Error}
 * @returns {String} how many keys effected
 */
async function flushFromCache(cacheCode) {
  const pattern = cacheCode ? ` --pattern ${cacheCode}_*` : "";
  const command = `redis-cli --scan${pattern} | xargs redis-cli del`;
  try {
    const execResult = await execAsync(command);
    // result looks like { stdout: string, stderr: string }.
    // stdout is populated when everything goes nicely.
    // stderr is populated if error occurred while running command
    if (execResult.stderr) {
      throw new Error(execResult.stderr);
    }

    // When there are keys deleted the result looks like:
    // (integer) 2
    // When there are no keys found the result looks like:
    // ERR wrong number of arguments for 'del' command
    let result;
    if (execResult.stdout.includes("ERR")) {
      result = `No ${cacheCode ? `'${cacheCode}'` : ""} keys to flush`;
    } else {
      result = `${execResult.stdout.trim()} ${
        cacheCode ? `'${cacheCode}'` : ""
      } keys flushed`;
    }
    return result;
  } catch (e) {
    // this error can occur if the command is bad
    throw new Error(e.message);
  }
}

module.exports = {
  flushFromCache
};

These articles were helpful:
https://stackabuse.com/executing-shell-commands-with-node-js/ https://stackoverflow.com/questions/20643470/execute-a-command-line-binary-with-node-js

No comments:

Post a Comment

I appreciate your time in leaving a comment!