nodejs中redis客户端的异步导出

时间:2021-04-22 07:25:03

标签: javascript node.js redis

以下代码构建了一个redis客户端并导出。我正在从保管库秘密管理服务获取 redis 密码,该调用是一个承诺/异步。该代码不会等待该调用,它会在异步调用完成之前导出 redis 客户端。我不确定我在这里做错了什么。有什么想法吗?

import redis from 'redis';
import bluebird from 'bluebird';
import logger from '../logger';
import srvconf from '../srvconf';
import { getVaultSecret } from '../services/vault.service';

const vaultConfig = srvconf.get('vault');

bluebird.promisifyAll(redis);

let redisUrl = '';
const maskRedisUrl = (url) => url.replace(/password=.*/, 'password=*****');
const setRedisUrl = (host, port, pw) => { 
  const pwstring = pw ? `?password=${pw}` : '';
  const url = `redis://${host}:${port}${pwstring}`;
  console.log(`Setting redis_url to '${maskRedisUrl(url)}'`);
  return url;
}

if (vaultConfig.use_vault) {
  (async () => {
    const secret = await getVaultSecret(`${vaultConfig.redis.secrets_path + vaultConfig.redis.key}`)
    redisUrl = setRedisUrl(srvconf.get('redis_host'), srvconf.get('redis_port'), secret.PASSWORD);  
  })().catch(err => console.log(err));
} else {
  if (!srvconf.get('redis_url')) {
    redisUrl = setRedisUrl(srvconf.get('redis_host'), srvconf.get('redis_port'), srvconf.get('redis_password'));;
  } else {
    redisUrl = srvconf.get('redis_url');
    console.log(`Found redis_url ${maskRedisUrl(redisUrl)}`);
  }
}

const options = redisUrl
  ? { url: redisUrl }
  : {};

const redisClient = redis.createClient(options);

redisClient.on('error', err => {
  logger.error(err);
});

export default redisClient;

1 个答案:

答案 0 :(得分:0)

问题是 (async () => {...})() 返回一个 Promise 而您没有在顶级 awaiting 它,因此脚本继续运行超过该行,设置 {{1 }} 并返回 options = {}

您需要的是 top-level await,它在 Node versions >= 14.8.0 中默认启用。但是,如果您的项目使用的版本早于此,则有如下解决方法。

请注意,以下代码未经测试,因为我在本地没有相同的项目设置。

模块

redisClient

用法

在您导入和使用客户端的所有地方,您总是需要检查它是否真的初始化成功,如果没有,则抛出(并捕获)一个定义良好的错误。

import redis from "redis";
import bluebird from "bluebird";
import logger from "../logger";
import srvconf from "../srvconf";
import { getVaultSecret } from "../services/vault.service";

const vaultConfig = srvconf.get("vault");

bluebird.promisifyAll(redis);

let redisUrl = "";
let redisClient = null;

const initRedisClient = () => {
  const options = redisUrl ? { url: redisUrl } : {};

  redisClient = redis.createClient(options);

  redisClient.on("error", (err) => {
    logger.error(err);
  });
};

const maskRedisUrl = (url) => url.replace(/password=.*/, "password=*****");
const setRedisUrl = (host, port, pw) => {
  const pwstring = pw ? `?password=${pw}` : "";
  const url = `redis://${host}:${port}${pwstring}`;
  console.log(`Setting redis_url to '${maskRedisUrl(url)}'`);
  return url;
};

(async () => {
  if (vaultConfig.use_vault) {
    try {
      const secret = await getVaultSecret(
        `${vaultConfig.redis.secrets_path + vaultConfig.redis.key}`
      );
      redisUrl = setRedisUrl(
        srvconf.get("redis_host"),
        srvconf.get("redis_port"),
        secret.PASSWORD
      );
    } catch (err) {
      console.log(err);
    }
  } else {
    if (!srvconf.get("redis_url")) {
      redisUrl = setRedisUrl(
        srvconf.get("redis_host"),
        srvconf.get("redis_port"),
        srvconf.get("redis_password")
      );
    } else {
      redisUrl = srvconf.get("redis_url");
      console.log(`Found redis_url ${maskRedisUrl(redisUrl)}`);
    }
  }
  // Initialize Redis client after vault secrets are loaded
  initRedisClient();
})();

export default redisClient;