redis-plus-plus icon indicating copy to clipboard operation
redis-plus-plus copied to clipboard

##Use a custom connection policy when IP port cannot be obtained directly##

Open rubicon0501 opened this issue 1 year ago • 1 comments

If specify the type of connection_options is ConnectionType::CUSTOM, it will use the customConnectFn create a connection to redis server. This allows users to implement their own connection logic. After all, in many cases, the domain name or IP address is not given directly. For example, in the scenario of deploying some Redis instances with a microservice mode, a service name is given.

We can use custom connect policy as follows. First, we define a function which can connect to redis server.

redisContext* customConnect(void *arg) {
    if (!arg) {
        // It is not necessary to throw an exception.
        // Because you do not need any parameters to obtain.
        throw Error("myConnectTCP parameter is invalid");
    }

    // If you need a parameter, type conversion is necessary when you know it's not nullptr.
    CustomConfType someConf = *(reinterpret_cast<CustomConfType*>(arg));
    
    // Do something as you need.
    // For example, obtain the real IP address through service discovery.
    doSomething();
	
    // Create a redisContext instance and return it's address.
    // Maybe you can refer to the following function.
    return redisConnect(hostIP.c_str(), hostPort); 

}

Parameter to be passed to the custom function.

ConnectionOptions connection_options;
CustomConfType myConf;
connection_options.type = ConnectionType::CUSTOM;  // It's required if you want to use custom connect policy.
connection_options.customConnect = customConnect;  // It's required if you want to use custom connect policy.
connection_options.customConnectArg = &(myConf);  // Optional. The default is nullptr.

Connect to Redis server with a single connection and customize connect policy. Redis redis2(connection_options);

rubicon0501 avatar Nov 25 '22 03:11 rubicon0501

Thanks for the contribution!

The proposed solution using a customConnectFn to create a redisContext, with customConnectArg. However, this solution has two problems.

  1. customConnectArg is a pointer, and might be destroyed. When the connection needs to be reconnected in the future, this data pointer might already been deleted.
  2. It creates redisContext directly, instead of reusing the code creating connection with ConnectionOptions. So when you want to specified connection timeout, you have to duplicate this part of code again.

You want to achieve some user defined DNS resolver, so why not only do this part of work? Design a DNS resolver interface, e.g. unique_ptr<DnsResolver>, and make it a member of Connection or ConnectionPool. When you need to create a connection, and DNS resolver is not null, call it to get the real IP and port.

Not sure if this solution is better. Still need some more thinking.

Regards

sewenew avatar Nov 27 '22 16:11 sewenew