RSS Git Download  Clone
Raw Blame History 2kB 84 lines
const Redis = require('ioredis')
const hash = require('object-hash')

const redisNodesCache = {}
module.exports = async function getClusterNodes(servers, options = {}) {

    const {
        cache = false,
        force = false,
    } = options

    if (!Array.isArray(servers)) {
        servers = [servers]
    }

    const errors = []

    let nodes
    for (const server of servers) {
        try {

            const id = cache ? hash(server) : null
            if (cache && !force && redisNodesCache[id]) {
                return redisNodesCache[id]
            }
            const redis = new Redis({...server, retryStrategy: () => false})

            const rawNodes = await new Promise((resolve, reject) => {
                redis.sendCommand(
                    new Redis.Command(
                        'CLUSTER',
                        ['NODES'],
                        'utf-8',
                        function (err, value) {
                            if (err)
                                reject(err)
                            else
                                resolve(value.toString())
                        }
                    )
                )
            })

            const lines = rawNodes.trim().split("\n")
            nodes = lines.reduce((arr, line) => {
                if (!line) {
                    return arr
                }
                const row = line.split(' ')
                const [
                    node_id,
                    server,
                    flags,
                ] = row
                const [target, slots] = server.split('@')
                const [host, port] = target.split(':')
                const node = {
                    host,
                    port,
                }
                arr.push(node)
                return arr
            }, [])
            if (cache) {
                redisNodesCache[id] = nodes
            }
            return nodes
        } catch (error) {
            console.error(error)
            errors.push(error)
        } finally {
            redis.disconnect()
        }
        if (nodes) {
            break
        }
    }
    if (nodes) {
        return nodes
    }
    const errorsMsg = errors.map(e => e.toString()).join(',')
    throw new Error('getClusterNodes errors: ' + errorsMsg)
}