Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

172
Visualizações
Why is JS redis looping more times after succesful write?

I have the following logic for reading and writing redis state

export async function updateRedis() {
let stateName = 'stateName'
try {
    let isSuccess = false
    while (!isSuccess) {
        try {
            await redis
                .watch(stateName, function (err) {
                    if (err) {
                        logger.error(`Error in watch state: ${err}`)
                    }
                    redis.get(stateName, function (err, result) {
                        if (err) {
                            logger.error(`Error in get state: ${err}`)
                        }

                        let state = JSON.parse(result)
                        // do some processing
                        redis.multi()
                            .set(stateName, JSON.stringify(state))
                            .exec(function (err, result) {
                                if (err) {
                                    logger.error(`Error in set state: ${err}`)
                                }
                                if (result != null) {
                                    isSuccess = true
                                }
                            })
                        console.log(`isSuccess for ${stateName} `, isSuccess)
                    })
                })
        } catch (e) {
            logger.error(`Error: ${e}`)
        }
    }
} catch (e) {
    logger.error(`Error: ${e}`)
}
return Promise.resolve(true)

}

This will print out

"isSuccess for stateName false"
"isSuccess for stateName true"
"isSuccess for stateName true"

So after the flag changes to true, it will continue for more loops. Sometimes it does more than just once.

Am I doing something wrong?

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

You cannot mix a synchronous loop (while (!isSuccess) { ... }) with asynchronous functions (redis.watch(stateName, function (err) { ... })).

You can also not await callback-based asynchronous functions. A function must return a promise to be awaitable. Since node-redis gives you promises when you don't pass callbacks to its methods, the key is not to do that (redis.watch(stateName, function (err) { ... }) → redis.watch(stateName)).

Your approach needs to be redone.

Let's make a function that encapsulates a redis transaction with optimistic locking. It takes a connection object, a key, and a value-transforming function, and it returns the result of the .set() operation:

const redisTransaction = async (client, key, transformer) => {
    // https://github.com/redis/node-redis/blob/master/docs/isolated-execution.md
    return client.executeIsolated(async isolatedClient => {
        await isolatedClient.watch(key);
        const val = await isolatedClient.get(key);
        return isolatedClient.multi()
            .set(key, await transformer.call(isolatedClient, val))
            .exec();
    });
};

Now you can await this function, because it returns a promise. That means we can make a simple infinite loop that exits immediately in case of success (via return), or retries indefinitely.

export async function updateRedis(key, transformer) {
    while (true) {
        try {
            return await redisTransaction(redis, key, transformer);
        } catch (err) {
            logger.error(`Error for state ${key}: ${err}`);
        }
    }
}

A transformer function takes a value, and returns a new value. Inside it, the this keyword refers to the isolatedClient from the transaction, which could be useful if your transformation depends on other values from that client.

const result = await updateRedis('stateName', async function (val) {
    const state = JSON.parse(val);
    const newState = await modifyStateSomehow(state);
    return JSON.stringify(newState);
});

The modifyStateSomehow() can itself be an asynchronous (i.e. "promise-returning") function. If it's not, you can make the state transformer a regular function by removing the async and the await.

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda