Problems using Railway's Redis Private Networking (Solved)

AnonymousTRIAL

a year ago

I have the following NestJs service:

import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { Redis } from 'ioredis';
import { EnvService } from 'src/env/env.service';

@Injectable()
export class RedisService extends Redis implements OnModuleInit {
  private readonly logger = new Logger(RedisService.name);
  public readonly redisUrl = this.envService.get('REDIS_URL');
  public readonly redisProtocol = this.envService.get('REDIS_PROTOCOL');

  constructor(private readonly envService: EnvService) {
    const redisUrl = envService.get('REDIS_URL');
    const redisProtocol = envService.get('REDIS_PROTOCOL');

    super(redisUrl, {
      family: redisProtocol,
      maxRetriesPerRequest: null,
      connectTimeout: 30000, // 30 seconds
    });

    this.redisUrl = redisUrl;
    this.redisProtocol = redisProtocol;

    this.logger.log('creating redis client', redisUrl, redisProtocol);
  }

  async onModuleInit(): Promise {
    await new Promise((resolve, reject) => {
      this.logger.log('connecting to redis...');

      this.on('connect', () => {
        this.logger.log('connected to redis');
        resolve();
      });

      this.on('error', (error) => {
        this.logger.error('Error connecting to Redis:', error);
        reject(error);
      });
    });
  }
}

In the Deploy Logs it prints the following values:

[Nest] 25 - 02/27/2024, 2:52:04 PM LOG [RedisService] creating redis client

[Nest] 25 - 02/27/2024, 2:52:04 PM LOG [RedisService] redis://default:BMdLME2HPo6igkB4bpgGHMMiA21MBiBI@redis-eblx.railway.internal:6379

[Nest] 25 - 02/27/2024, 2:52:04 PM LOG [RedisService] 6

[Nest] 25 - 02/27/2024, 2:52:09 PM ERROR [RedisService] Error connecting to Redis:

[Nest] 25 - 02/27/2024, 2:52:09 PM ERROR [RedisService] Error: getaddrinfo ENOTFOUND redis-eblx.railway.internal

Any idea on what I am doing wrong?

1 Replies

AnonymousTRIAL

a year ago

03b9d68c-2d80-4600-a0a4-317a53176c97


a year ago

please have a look at this docs section


AnonymousTRIAL

a year ago

I see this in the docs

ioredis is a Redis client for node.js, commonly used for connecting to Redis from a node application. When initializing a Redis client using ioredis, you must specify family=0 in the connection string to support connecting to both IPv6 and IPv4 connections:

import Redis from 'ioredis';

const redis = new Redis(process.env.REDISPRIVATEURL + '?family=0');

const ping = await redis.ping();

When I update my constructor to the following it unfortunately still doesn't work.

constructor(private readonly envService: EnvService) {
  const redisProtocol = envService.get('REDIS_PROTOCOL');
  const redisUrl = `${envService.get('REDIS_URL')}?family=${redisProtocol}`;

  super(redisUrl, {
    maxRetriesPerRequest: null,
    connectTimeout: 30000, // 30 seconds
  });

  this.redisUrl = redisUrl;
  this.redisProtocol = redisProtocol;

  this.logger.log('creating redis client', redisUrl, redisProtocol);
}

Logs:

[Nest] 26 - 02/27/2024, 3:34:13 PM LOG [RedisService] creating redis client

[Nest] 26 - 02/27/2024, 3:34:13 PM LOG [RedisService] redis://default:BMdLME2HPo6igkB4bpgGHMMiA21MBiBI@redis-eblx.railway.internal:6379?family=0

[Nest] 26 - 02/27/2024, 3:34:13 PM LOG [RedisService] 0

[Nest] 25 - 02/27/2024, 3:34:41 PM ERROR [RedisService] Error connecting to Redis:

[Nest] 25 - 02/27/2024, 3:34:41 PM ERROR [RedisService] Error: getaddrinfo ENOTFOUND redis-eblx.railway.internal


AnonymousTRIAL

a year ago

With the public URL it works no problem


AnonymousTRIAL

a year ago

Thanks for taking the time to respond.


a year ago

looks like you are complicating things quite a bit, just try setting family to 0 in the options object please


a year ago

are you deploying with nixpacks?


AnonymousTRIAL

a year ago

Looks like it


a year ago

okay cool, please try my suggestion


AnonymousTRIAL

a year ago

When I do "const redisUrl = envService.get('REDIS_URL') + '?family=0';" it works, you right. Not sure why, it logs the same


a year ago

awsome!


AnonymousTRIAL

a year ago

Any idea why?


a year ago

typo?


AnonymousTRIAL

a year ago

When I use a text compare tool it is the same. No idea, I don't really have the time to look into it at the moment. Thanks a lot!


AnonymousTRIAL

a year ago

Problems using Railway's Redis Private Networking (Solved)


a year ago

no problem!


AnonymousTRIAL

a year ago

<@539512869780455445>, nvm, seems like this one time was luck


AnonymousTRIAL

a year ago

Problems using Railway's Redis Private Networking


a year ago

okay can you add a 3 second sleep to your start script as to delay the starting of your app


AnonymousTRIAL

a year ago

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { EnvService } from './env/env.service';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const envService = app.get(EnvService);
  app.enableCors();
  await app.listen(envService.get('PORT'));
}
bootstrap();

Before NestFactory.create or after?


a year ago

please add the sleep in the start script, theres really no need to overcomplicate the solutions im trying to provide 🫤


AnonymousTRIAL

a year ago

Ah, I think you mean here like this

"start:prod": "sleep 3 && node dist/main"

I am not over-complicating it on purpose. I am unsure what a "start script" is from your perspective. The package.json script, the code initializing the application, etc.


a year ago

thats correct


AnonymousTRIAL

a year ago

Seems like it is helping. Why?


a year ago

the private network's dns resolver takes about 3 seconds to start answering lookup requests, though its still only ipv6, so you do need family: 0 still


AnonymousTRIAL

a year ago

Ok, thanks you, interesting. Even after multiple restarts it is working. I will increase it to 5 seconds just to be sure


AnonymousTRIAL

a year ago

Problems using Railway's Redis Private Networking (Solved)


a year ago

i dont think theres a need for 5 seconds, over a 7 day period the slowest resolver ready time was only ~2.3 seconds


AnonymousTRIAL

a year ago

Interesting stats, very good to know. Now the private networking is solid. Thanks for the patience, I highly appreciate it <:salute:1137099685417451530>


a year ago

no problem! and for the record the team is working to remove any and all startup delays


AnonymousTRIAL

a year ago

Great, can't wait, less unexpected stuff to worry about!


a year ago

less help threads for me too, though it wont solve the need for the family 0 config


a year ago

thats something ioredis really should change, since it currently defaults to ipv4 only (family 4)


AnonymousTRIAL

a year ago

Yeah, I had it on family 6, which did work once, but then after another redeploy it didn't work and I though I had introduced a bug, but seems like the sleep was missing. Ipv6 generally still feels like a earlier adopter thing or like an afterthought, which is ridiculous


mbrooksonPRO

a year ago

Just came across this same issue with ioredis and solved by setting family=0, thanks!

Just for clarification to anyone else who finds this, the family option can take one of the following values:

  • 4: Use IPv4 protocol family. (default)

  • 6: Use IPv6 protocol family.

  • 0: Let the operating system decide which protocol family to use.