Make redis config node more "dynamic"

In this project GitHub - golfvert/WIS2-GlobalBroker-NodeRed: Basic reference of a Global Broker for WIS2 available as a ready to use container, I am making use of https://flows.nodered.org/node/node-red-contrib-redis .
This contrib node works great.
At the moment, I am using redis in a non-cluster mode. And as part of the setup, a redis instance must be on the same docker bridged network.
I'd like to change that and be able to use an existing redis service that could be in cluster to improve reliability.
However, the current node doesn't permit the configuration of the cluster mode dynamically (eg. through an ENV variable or using dynamic msg input). Typically, what is possible with the excellent MQTT nodes.

I wonder what are the options here.

  1. asking the maintainer to add this feature ? I've done that, maybe that will happen...
    If not, some ideas on Plan B:
  2. forking the repo and add this feature myself. Is there some simple example how I could use to do that. Typically, another contrib node having this feature that I could "borrow"...
  3. having two config nodes one with cluster and one without and be able to switch dynamically at startup ? Not sure if that is doable as the flows.json is part of the container and is not stored on a permanent volume.

Some other ideas ?
Thanks for your clues :slight_smile:

Have you tried using env vars?

https://nodered.org/docs/user-guide/environment-variables#setting-a-node-property

Any node property can be set with an environment variable by setting its value to a string of the form ${ENV_VAR}. When the runtime loads the flows, it will substitute the value of that environment variable before passing it to the node.

This only works if it replaces the entire property - it cannot be used to substitute just part of the value. For example, it is not possible to use CLIENT-${HOST}.

As nodes provide their own edit dialog, not all properties will provide a text input that can be used to enter the env-var string. In that case, you may consider hand-editing the flow file to set the property.

I have...
The config screen of the redis server looks like this:

The "option" (that is the name of the server) can be set using ENV. No problem.
The "cluster" being a tick box can (only?) be via the interface.

I know that in eg. the MQTT config node the TLS option is a tick box but can be defined with an ENV variable through the broker url config. I guess the js is more clever than the one from the redis node. Looking at the code of this redis node (node-red-contrib-redis/redis.js at master · chameleonbr/node-red-contrib-redis · GitHub)
I can't see it being able to parse any ENV variable to get the true/false option I am looking for.

The code of the node for the cluster part is:

    try {
      if (config.cluster) {
        connections[id] = new Redis.Cluster(options);
      } else {
        connections[id] = new Redis(options);
      }

config.cluster being the tick box above.

I have considered changing the flows.json out of the UI before publishing the docker container (the flow file is part of the container and can't be changed - by design).

However, ${ENV_VAR} are strings and the cluster option waits for true or false (and not "true" or "false"). This is where I am stuck.

From what I can see, if you were to set the "redis-config" node property "cluster": "${CUSTER}" in the flow file AND set the actual env var CLUSTER to anything it would pass as truthy. Leaving it unset would be falsy and therefore should work

I have tried that... Unfortunately, it is kinda the opposite.

The redis-config node:

    {
        "id": "8f497140bcbdd802",
        "type": "redis-config",
        "name": "Redis",
        "options": "REDIS_URL",
        "cluster": "${REDIS_CLUSTER}",
        "optionsType": "env"
    },

Then even if REDIS_CLUSTER env var does not exist (it will/should be evaluated to "cluster": "") and it ticks the box :frowning:
The only way for cluster to be off, is with "cluster": false

Ah, perhaps try setting the env var REDIS_CLUSTER to an empty string?

I think if the environment variable doesn't exist then the value ${REDIS_CLUSTER} is being used?

Quite easy to check with a temporary console log entry added directly into the source file.

try {
      console.log("config.cluster =  ", config.cluster) // add this
      if (config.cluster) {
        connections[id] = new Redis.Cluster(options);
      } else {
        connections[id] = new Redis(options);
      }

To be fair, this may be a flaw (or rather a design choice) where it doesn't discern the subtle differences between missing and empty. Give it a go. See what happens. Let us know.

It seems to be the case...

I have modified the redis.js with what you gave me:

If the env variable is not set or is set with nothing (ie. no value) when the container starts, I get:

config.cluster =   ${REDIS_CLUSTER}

When:

      - REDIS_CLUSTER=123

Then I get:

config.cluster =   123

Thanks for the help !

That is unfortunate. In an ideal world where we all wear hindsight glasses, an empty (but defined) env-var would evaluate to '' but that would be a breaking change now.

There is still hope.

try adding it to THE TOP your settings.js (before module.exports) as follows...

process.env.REDIS_CLUSTER=false

What does console.log("config.cluster = ", config.cluster) show you now?


Other tests I would perform are...

process.env.REDIS_CLUSTER=0
process.env.REDIS_CLUSTER=''
process.env.REDIS_CLUSTER=null

With:

        "cluster": "${REDIS_CLUSTER}"

in flows.json.

All options: false, 0, '', null of process.env.REDIS_CLUSTER= end up with the tick box activated in the Redis configuration node :cry:

ok, but What does console.log("config.cluster = ", config.cluster) show you?

Have you confirmed that if you export the flows, the field is still set to ${REDIS_CLUSTER}?

Did you restart node-red and hard refresh browser?

console.log("config.cluster = ", config.cluster) gives the value sets in settings.js with false, 0, null.
Only '' gives ${REDIS_CLUSTER}.

I am running node-red in Docker. After each change, I restarted the container and reloaded the web page.
I also have a very basic test that works when the box is unticked. And with all those values, it fails. So, the tick box is not related to some caching issue.

well I guess you are going to have to either pre-load a modified version or fork it :man_shrugging:

The "good" fix to use env vars is to change the option to a typedInput (permitting a choice of "bool" and "env") and ensure you do a more specific test (like below)


The quick fix is to leave the UI alone and just be more specific on the test:

try {
      console.log("config.cluster =  ", config.cluster) // add this
      if (config.cluster === "true" || config.cluster === true) {
        connections[id] = new Redis.Cluster(options);
      } else {
        connections[id] = new Redis(options);
      }

I guess that will be the solution.

At the moment, the dependencies in package.json fetches the official contrib mode. I need to understand how to use my own...
Thanks again for your help.
Enjoy what is left of Sunday :slight_smile:

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.