Giter Club home page Giter Club logo

redis-plus-plus's People

Contributors

alnr avatar anders94 avatar andrzejc avatar asphalt415 avatar beyondwuxf avatar bratsinot avatar ericdeng1001 avatar hsnks100 avatar jakesylvestre avatar jbrezina avatar jengdib avatar jiningh avatar kraj avatar msardonini avatar paceholder avatar paulo-erichsen avatar pbronneberg avatar picanumber avatar prince-chrismc avatar reneetse avatar s-bohn avatar sewenew avatar shuyumo2003 avatar stefankarlsson321 avatar tedlyngmo avatar twoixter avatar victor-timofei avatar viniciosbarros avatar vladcioaba avatar wingunder avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

redis-plus-plus's Issues

test with standalone mode

I installed redis 5 and run it as standalone server.
When try test application with following command:
./compile/test/test_redis++ -h localhost -p 6379 -n localhost -c 6379

But get following error:
Test failed: ERR This instance has cluster support disabled

Need a way to run test with standalone server.

Redis object

Hello, is there any way of creating a sw::redis::Redis object without passing anything, and then connect the object to redis afterward?

sw::redis::Redis *redis = new sw::redis::Redis(config) <- this run np on mac os with clang, but have bad_alloc issue on ubuntu with g++.

Also, is there any way to check the connection result? Thank you.

Using redis-plus-plus with FetchContent / ExternalProject_Add

Hey Guys, is there any possibility to use redis-plus-plus (and hiredis) with FetchContent and linking it to my executable? I can successfully build hiredis but since it wont be in the default path i need to pass arguments to redis-plus-plus. So I ended up mixing it with ExternalProject_Add.. but I still get the following error:

cmake_minimum_required(VERSION 3.16)
include(FetchContent)
FetchContent_Declare(
        hiredis
        GIT_REPOSITORY https://github.com/redis/hiredis.git
        GIT_TAG master
        SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/hiredis-src/hiredis
)
FetchContent_MakeAvailable(hiredis)

project(redisgraph)
set(CMAKE_CXX_STANDARD 17)

include(ExternalProject)
ExternalProject_Add(
        redis_pp
        GIT_REPOSITORY https://github.com/sewenew/redis-plus-plus
        GIT_TAG 1.1.1
        INSTALL_DIR ${CMAKE_BINARY_DIR}/_deps/redis_pp
        CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=${hiredis_BINARY_DIR} -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/_deps/redis_pp -DREDIS_PLUS_PLUS_BUILD_TEST=OFF)

include_directories(include)

get_filename_component(ACTUAL_HIREDIS_DIR ${hiredis_SOURCE_DIR} PATH)
include_directories(${ACTUAL_HIREDIS_DIR})
include_directories(${CMAKE_BINARY_DIR}/_deps/redis_pp/include)

file(GLOB SOURCE_FILES
        "src/*.cpp"
        )

add_library(redisgraph ${SOURCE_FILES})
add_dependencies(redisgraph redis_pp)
target_link_libraries(redisgraph hiredis)

add_executable(test example/main.cpp)
target_link_libraries(test redisgraph)

With the following symbols not found error:

Undefined symbols for architecture x86_64:
  "sw::redis::Redis::auth(sw::redis::StringView const&)", referenced from:
      _main in main.cpp.o
  "sw::redis::Redis::Redis(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)", referenced from:
      _main in main.cpp.o
ld: symbol(s) not found for architecture x86_64

The main.cpp only has

#include <sw/redis++/redis++.h>
int main() {
auto redis = sw::redis::Redis("tcp://127.0.0.1:6379");
}

Remove extra memory allocation in parse()

When using redis-plus-plus to send large messages, I noticed during memory profiling with valgrind massif that a heap allocation occurs when then redisReply object is transformed into a std::string (i.e. return std::string(reply.str, reply.len); ). Is there anyway to restructure this function or API slightly to eliminate this extra copy? This would really help manage peak memory utilization when sending large messages through redis-plus-plus.

Add single key overload method for some command

Some commands have single key format, e.g. BITOP operation destkey key. However, by now, we only have multiple-key overloads for these commands, and we need to add support for these commands.

core dumped: Assertion `!connection.broken()' failed !

An error occurred when I run the test code:
try {
// Create an Redis object, which is movable but NOT copyable.
auto redis = Redis("tcp://127.0.0.1:6379");

// ***** STRING commands *****

redis.set("key", "val");
auto val = redis.get("key");    // val is of type OptionalString. See 'API Reference' section for details.
if (val) {
    // Dereference val to get the returned value of std::string type.
    std::cout << *val << std::endl;
}   // else key doesn't exist.

// ***** LIST commands *****

// std::vector<std::string> to Redis LIST.
std::vector<std::string> vec = {"a", "b", "c"};
redis.rpush("list", vec.begin(), vec.end());

// std::initializer_list to Redis LIST.
redis.rpush("list", {"a", "b", "c"});

// Redis LIST to std::vector<std::string>.
vec.clear();
redis.lrange("list", 0, -1, std::back_inserter(vec));
} catch (const Error &e) {
cout << e.what() << endl;
}

Assertion `!connection.broken()' failed.
But redis set and get be successful.And this error will also occur when calling template command function like "lrange" "hmset" and so on.I hope get your help. thanks!

more example for script

thank you for this great job
can you provide some more lua script reply parse example?
ex: script return 0 "1" [1,2,3] (number string ,array(int/string))

How to get information about cluster nodes ?

I'm writing a simple redis client for publish/subscribe massages. I use configured redis cluster with 3 docker-machines where each have in it 2 nodes (master and slave). It works so far so good. But i have trouble to set starting IP to connect with redis cluster. As You mentioned in documentation you only need to set one master node's host & port, but after one machine failure and reboot masters and slaves have different IP (the slave become master etc.). So after restarting my client i have to set new master IP in connection settings, because it won't connect with a slave IP.

So Is there any option like in hredis-vip to set many IP in connect options ? If not. How am I able to find masters ip and then setup connection with available master? I tried to read cluster info using command CLUSTER SLOTS, but it didn't work. I followed your instructions about Generic Command Interface, but there always throw an error.

        RedisCluster cluster2(connection_options[2]);
        //connection_options[2].host = "192.168.99.112";
        //connection_options[2].port = 32768;
        auto r = cluster2.command("cluster","slots");
        assert(r);
        std::vector<OptionalString> result;
        result = reply::parse<std::vector<OptionalString>>(*r);
    }
    catch(const Error &e){
        cout << "Cluster slots error" << endl;

    }

Edit 1:
I tried also, but still doesn't work:

        std::vector<OptionalString> result;
        auto r = cluster2.command("cluster", "slots");
        assert(r);
        reply::to_array(*r, std::back_inserter(result));

Edit 2:
I find commend "ROLE" which would help me. It shows information about node, its role and assigned slots.

1) "slave"
2) "192.168.99.113"
3) (integer) 32770
4) "connected"
5) (integer) 33516

But i cannot pass Redis::command with a single parameter.
auto r = cluster2.command("ROLE"); doesn't work.

add is_valid to Redis transaction

Consider the following scenario. I have got a pool of Redis transactions, in the pool I store thin wrappers around sw::redis::transaction and upon destruction of the wrapper I put sw::redis::transaction back to the pool assuming the transaction is still valid. What I do now is (pseudo code):

Wraper::~Wrapper()
{
if (!std::uncaught_exception())
{
  pool.push_back(transaction);
}
}

That is not a perfect solution since the exception can be not related to Redis at all. Also what I would like to do is discard transaction before putting in back to the pool, in case somebody left unexecuted commands in the transaction. So I would like to have something like that:

Wraper::~Wrapper()
{
if (transaction->is_valid())
{
  if (transaction->in_transaction())
  {
    transaction->discard();
  }
  pool.push_back(transaction);
}
}

My proposal to make it work would be adding the following functions:

bool QueuedRedis::is_valid() { return _valid; }
bool QueuedRedis::is_in_transaction() { return _impl.is_in_transaction(); }
bool TransactionImpl::is_in_transaction() { return _in_transaction; }
bool PipelineImpl::is_in_transaction() { return false; }

Would that make sense? Is there any other way to achieve that behaviour?

how select db number form redis Sentinel

ConnectionOptions connection_opts;
//connection_opts.password = "auth"; // Optional. No password by default.
connection_opts.connect_timeout = std::chrono::milliseconds(200); // Required.
connection_opts.socket_timeout = std::chrono::milliseconds(200); // Required.
connection_opts.db = 1;

ConnectionPoolOptions pool_opts;
//pool_opts.size = 3; // Optional. The default size is 1.

_redis = new Redis(sentinel, "mymaster", Role::MASTER, connection_opts, pool_opts);

I want to change the number of db,how?

Always return false when calling method from worker thread.

Hi, I using Redis Cluster client.

In all methods, worker threads are prevented from performing normal operations.

  1. RedisClusterClient object (main thread)
  2. hset is working ok. (main thread)
  3. hset is alway not working. (worker thread)

My dev environment.

  • c++14
  • cpprestsdk (pplx)

PS. I'm not native speaker. sry.

Issue with the connection pool

Hi,

many thanks for the great library ! I have got to this weird problem. I have an application with a lot of interaction with redis. Most of my interaction are through pipeline. I use the connection pool with 30 connections and I have set the keepalive option to true. However I have still a lot of IN_WAIT TCP connection and I have "Failed to connect to Redis: Cannot assign requested address" errors that are resulting from the port space becoming full. I do not understand why the pool is not used.

Here is my code for generating the connection
Redis *bgpRedisConnect(string host, int port, int dbase){
try {
ConnectionOptions connection_options;
connection_options.host = host; // Required.
connection_options.port = port; // Optional. The default port is 6379.
connection_options.db = dbase;// Optional. Use the 0th database by default.
connection_options.keep_alive=true;
// connection_options.type = ConnectionType::UNIX;
// connection_options.path = "/var/run/redis/redis.sock";

    // Optional. Timeout before we successfully send request to or receive response from redis.
    // By default, the timeout is 0ms, i.e. never timeout and block until we send or receive successfuly.
    // NOTE: if any command is timed out, we throw a TimeoutError exception.

// connection_options.socket_timeout = std::chrono::milliseconds(500);

    ConnectionPoolOptions pool_options;
    pool_options.size = 30;  // Pool size, i.e. max number of connections.

    // Create an Redis object, which is movable but NOT copyable.
    return new Redis(connection_options, pool_options);
} catch (const Error &e) {
    std::cout<<"Redis connection error:"<<e.what()<<endl;
    return NULL;            // Error handling.
}

}

I thereafter reuse this same connection is several thread (16).

Many thanks for your help.

Cluster Moved not working

Hello,
i'm trying to use the ClusterRedis class, but it seems not to follow the redirect when needed.

For example I tried an rpush or an expire, but I get a ReplyError, in which the what() says: 8442 10.10.24.66:7002

I also tried to use a transaction, sending the commands in different parts of code, like this:
`
try{
auto tx = cluster.transaction("key");
insertPoints("key", tx);
auto replies = tx.exec();
}catch (ReplyError& rep) { cout << rep.what() << endl; }

//////////insertPoints def/////////////////
void insertPoints(string k, Transaction& tx){
tx.rpush(k, value);
tx.expire(k, seconds);
}

`

Why is script_load(), script_exists(), script_flush() and script_kill() not available in RedisCluster?

Given a Redis cluster, one could load a script into a Redis cluster node, using:

$ redis-cli -c -h 127.0.0.1 -p 7000 SCRIPT LOAD "return redis.call(\"PING\")"
"dc9acaa27306c368e1f1eb390e9b0dc9ec7314ee"

$ redis-cli -c -h 127.0.0.1 -p 7000 SCRIPT EXISTS dc9acaa27306c368e1f1eb390e9b0dc9ec7314ee
1) (integer) 1

This command loads the script only into the 127.0.0.1:7000 node and unless explicitly loaded into all other cluster nodes, none of the rest of the cluster nodes will have this script. So, if one connects to the 127.0.0.1:7001 node, in the same cluster, the loaded script won't exist, as it wasn't loaded to that node yet:

$ redis-cli -c -h 127.0.0.1 -p 7001 SCRIPT EXISTS dc9acaa27306c368e1f1eb390e9b0dc9ec7314ee
1) (integer) 0

All of this seems to be expected/designed redis-cli behavior and it seems to be the user's problem to get the script over to the other cluster nodes, if needed. Obviously the user might be in trouble if the client loaded a script onto the connected node and reconnects, possibly to another node. In this case, the script will not be in the Redis cache. With redis-cli, the user is expected to work around this problem at the moment.

The script_exists(), script_flush() and script_kill() functions also only operate on the connected node, when using redis-cli.

Would you agree that, at the moment, there is no reason not to allow script_load(), script_exists(), script_flush() and script_kill() to be available in RedisCluster, as long as we mimic the behavior of redis-cli?

To implement the above is probably straight forward.

One could of course also go the long, slow and complicated way and ensure that RedisCluster::script_load(), RedisCluster::script_exists(), RedisCluster::script_flush() and RedisCluster::script_kill() operate on all cluster nodes.

Eg: RedisCluster::script_load() could load a script into all cluster nodes like this:

  1. Use the CLUSTER SLOTS command in order to get all the cluster nodes, as was originally posted by @sewenew in #17 (comment).
  2. For each cluster node:
    1. establish a connection, using the Redis class constructor (not RedisCluster).
    2. load the script, using Redis::script_load()

I am not in favor of the last method, as operating on a script on all nodes will be impossible if some nodes are down. It will be better to simply just operate on scripts of the current connected node and let it up to the user to worry about the script calls on other cluster nodes.

Remove setbit interfaces

In some platform, there's a setbit macro, and will be conflict with Redis::setbit, RedisCluster::setbit and QueuedRedis::setbit.

We need to remove these setbit interfaces. If users need to send SETBIT command, they can use the generic command interface:

auto res = redis.command<long long>("SETBIT", "kkkkk", 7, 1);

Will `Redis& RedisCluster::redis(const StringView &hash_tag);` be possible?

Would it be possible to have the following member function in RedisCluster's public interface?

Redis& RedisCluster::redis(const StringView &hash_tag);

It will be very useful for something like this:

template <typename T>
class RedisMaster
{
public:
        RedisMaster(T& instance);

        Redis& getInstance();

private:
        T& _instance;
};

template<>
Redis& RedisMaster<Redis>::getInstance() {
        return _instance;
}

template<>
Redis& RedisMaster<RedisCluster>::getInstance() {
        return _instance.redis("");
}

At the moment I cannot get the above to work, as _instance.redis("") returns Redis and not Redis&.

Alternatively, is there another way to do the above?

Thanks & regards

VC2017 build on windows

Can't build on windows. Issues with find_path(HIREDIS_HEADER hiredis), find_library(HIREDIS_LIB hiredis) when the hiredis on different folder. What are the expectations with the dependent hiredis lib. I have hiredis in different folder here the folder structure, what should be the values for HIREDIS_HEADER & HIREDIS_LIB. tried with the these paths still report errors.

"C:\xxxx\redis\redis-plus-plus"
"C:\xxxx\redis\hiredis_lib"

  • "C:\xxxx\redis\hiredis_lib\install\include\hiredis\read.h"
  • "C:\xxxx\redis\hiredis_lib\install\include\hiredis\sds.h"
  • "C:\xxxx\redis\hiredis_lib\install\include\hiredis\async.h"
  • "C:\xxxx\redis\hiredis_lib\install\include\hiredis\hiredis.h"
  • "C:\xxxx\redis\hiredis_lib\install\lib\hiredis.dll"

Errors
Severity Code Description Project File Line Suppression State
Error CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
C:/xxxx/redis/redis-plus-plus/HIREDIS_HEADER
used as include directory in directory C:/xxxx/redis/redis-plus-plus
used as include directory in directory C:/xxxx/redis/redis-plus-plus
C:/xxxx/redis/redis-plus-plus/test/HIREDIS_HEADER
used as include directory in directory C:/xxxx/redis/redis-plus-plus/test
HIREDIS_LIB
linked by target "shared" in directory C:/xxxx/redis/redis-plus-plus
HIREDIS_STATIC_LIB
linked by target "test_redis++" in directory C:/xxxx/redis/redis-plus-plus/test
Error CMake Error at C:\xxxx\redis\redis-plus-plus\CMakeLists.txt:44 (install):
install Library TARGETS given no DESTINATION! redis C:\xxxx\redis\redis-plus-plus\CMakeLists.txt 44

Initializing Redis++ on IDE

Hi, thanks for your work.
I try to compile a simple cpp program:

#include <sw/redis++/redis++.h>

using namespace sw::redis;

int main()
{
auto redis = Redis("tcp://127.0.0.1:6379");
return 0;
}

but that script generate an error:

/home/user/Developments/clang/redis_test/main.cpp:10: undefined reference to sw::redis::Redis::Redis(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)' CMakeFiles/redis_test.dir/main.cpp.o: In function sw::redis::Connection::ContextDeleter::operator((redisContext*) const':
/usr/local/include/sw/redis++/connection.h:132: undefined reference to `redisFree'

Is there a simplest example do you provide for initiating redisDB?

Where is the default installation path of Redis++ header?

CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
(my project)/REDIS_PLUS_PLUS_HEADER

I've installed Redis++ with default prefix, but CMake doesn't recognize REDIS_PLUS_PLUS_HEADER. hiredis directory exists in /usr/local/include but Redis++ doesn't.

How to I fix this?

Issue with Sentinel support

Hi, I am using the Sentinel class to connect to a slave and having a problem. Everything is fine until I get an exception from a command and from then on it starts returning data from previous commands instead of the current one. Maybe something is not getting reset properly after the Exception (when reconnecting to Redis?)

It appears to work fine when I connect directly to the slave with the Redis class. (Although my test program hasn't thrown an exception yet to see if it starts getting the correct data after that).

Thanks for any help.

Is the 'Redlock' mechanism supported in this library?

I am aware that a transaction mechanism is available and that it works with both clustered and non-clustered Redis instances. However, as far as I understand it, the transaction mechanism can't be used to synchronize over Redis instances, as it would need to have a DLM (Distributed Lock Manager) for doing this. 'Redlock' is a specification for such a DLM.

According to the Distributed locks with Redis page, a C++ implementation of 'Redlock' exists here. However, it seems to lack cluster support, as it uses hiredis, as back-end.

A 'Redlock' implementation will be very handy within, as well as a nice supplement to this library.
Are there any plans for implementing this?

how to deal vector or list keys/args

now can use
std::initializer_listsw::redis::StringView keys = { "uid:10136387:record","uid:10136387:all","uid:10136387:empty" };
std::initializer_list<sw::redis::StringView > args = { "0","-20","0" };

but sometimes we need this
std::vectorstd::string keys;
keys.push_back("uid:10136387:record");
keys.push_back(....);

so it cannt complie how to do for this

Support C++17

Many modern compilers already have good support for C++ 17, and redis-plus-plus uses StringView and Optional<T> as replacements for std::string_view and std::optional<T>. In fact, if user already has a compiler supporting C++ 17, we should make redis-plus-plus use std::string_view and std::optional<T>, instead of those replacements.

I think we can do some compiler check to decide whether we should compile redis-plus-plus with C++11 or C++ 17.

use Redis Cluster

code:

    SentinelOptions sentinel_opts;
    sentinel_opts.nodes = {{"20.200.45.227", 26379},
                           {"20.200.45.226", 26379},
                           {"20.200.45.228", 26379}};   // Required. List of Redis Sentinel nodes.

    sentinel_opts.password ="itc123";
    sentinel_opts.connect_timeout = std::chrono::milliseconds(200);
    sentinel_opts.socket_timeout = std::chrono::milliseconds(200);

    ConnectionOptions connection_opts;
    connection_opts.password = "itc123";  // Optional. No password by default.
    connection_opts.connect_timeout = std::chrono::milliseconds(100);   // Required.
    connection_opts.socket_timeout = std::chrono::milliseconds(100);    // Required.

    ConnectionPoolOptions pool_opts;
    pool_opts.size = 3; // Optional. The default size is 1.

    auto sentinel = std::make_shared<Sentinel>(sentinel_opts);;
    auto redis = Redis(sentinel, "sms", Role::MASTER, connection_opts, pool_opts);

    while(1)
    {
        OptionalStringPair pair;
        pair = redis.brpop("list:mt:61", 200);

       sleep(1);
   }

error:
terminate called after throwing an instance of 'sw::redis::Error'
what(): Failed to create connection with sentinel
Aborted (core dumped)

Is there something wrong with my operation process?

[Question] Use Redis as class property

Hi,

I would like to use Redis instance as class property, but didn't succeed yet.

.h

#include <sw/redis++/redis++.h>

class MemoryStorage {
    public:
        MemoryStorage(bool throwException);
        ~MemoryStorage();
    private:
        sw::redis::Redis mRedis;
};

.cpp

#include "MemoryStorage.h"

MemoryStorage::MemoryStorage(bool raiseExceptions) {
    this->rconnect(raiseExceptions);
}

MemoryStorage::~MemoryStorage() {
    
}

void MemoryStorage::rconnect(bool raiseExceptions) {
    this->mRedis = new sw::redis::Redis("tcp://127.0.0.1:6379");
}

You know what's wrong ?

Additional ConnectionOptions constructor request.

Would it make sense to add the following ConnectionOptions constructor?

explicit ConnectionOptions(
    const ConnectionType &type = ConnectionType::TCP,
    const std::string &password = "",
    int db = 0,
    const std::string &host = "localhost",
    int port = 6379,
    bool keep_alive = true,
    const std::chrono::milliseconds &connect_timeout = std::chrono::milliseconds(0),
    const std::chrono::milliseconds &socket_timeout = std::chrono::milliseconds(0));

Currently, only the following constructor is available:

explicit ConnectionOptions(const std::string &uri);

The keep_alive is suggested to be true, due to issue #30.

Connection Broken when ConnectionOptions::socket_timeout is set

Hi, I'm have a problem with the Subscriber class when setting a ConnectionOptions::socket_timeout.
Basic example:

int main(int argc, char const *argv[])
{
	using namespace sw::redis;
	using namespace std::chrono_literals;
	ConnectionOptions connection_option;
	connection_option.host = "127.0.0.1";
	connection_option.port = 6379;
	// connection_option.socket_timeout = 10ms; /* comment out to obtain the error */

	auto redis = Redis(connection_option);
	auto sub = redis.subscriber();
	sub.on_message([](std::string channel, std::string msg) {
		std::cout << "Get " << msg << " on " << channel << std::endl;
	});
	sub.subscribe("topic_1");
	while (redis.ping() == "PONG")
	{
		try
		{
			sub.consume();
		}
		catch (const TimeoutError &timeout)
		{
			std::cout << "TIMEOUT" << std::endl;
			continue;
		}
		catch (const Error &err)
		{
			std::cout << err.what() << std::endl;
		}
		std::cout << "Pass" << std::endl;
		std::this_thread::sleep_for(100ms);
	}
	std::cout << "Exit" << std::endl;
	return 0;
}

All test are done voluntarily with no one publishing on that topics.
Without the explicit set of socket_timeout, all works as expected:

  • a first pass is write
  • connection is blocked since there is no incoming messages.

With the explicit set of socket_timeout (comment out the specific line), the output is:

  • Pass
  • Failed to get reply: Unknown error code
  • Pass
  • Connection is broken
  • Pass
  • Connection is broken
    [so on and so forth]

NOTE: the connection is broken after some seconds
In this case I would expect to see a TIMEOUT print, but no one is printed.
In my case, this behavior is 100% repeatable.
This error could be related to this modification? Am I missing something?

Thanks in advance!

Question: is Redis Object is thread-safe

Hi

When Redis with a single connection. The connection seems like shared in multi-threads without any protection. So as the underlying redisContext object.
redisContext itself is not thread safe. Does that means the Redis object in this case is also thread unsafe?

[TEST][MinGW][Win10] Redis-plus-plus Test under MinGW

Hi @sewenew,
I open an "issue" to keep track of tests under MinGw. Maybe someone is interested in them,

Preface

I'm running redis 4.0 under Windows 10 natively (NO WSL), so I could not test some redis 5.x functionalities. Sorry about that but I was not able to find a Win10-native redis 5.0 distribution.
For this reason, I need to comment out:

  • _test_zpop() (zset_cmds_test.hpp)
  • _test_bzpop() (zset_cmds_test.hpp)
  • _test_stream_cmds() (stream_cmds_test.hpp)
  • _test_group_cmds() (stream_cmds_test.hpp)

Currently I'm not setting up a RedisClaster, I should update this topic once I can test Cluster too.
Trying to run _test_multithreads with pool_opts.size = 10 bring my virtual machine to never ends test.. I tried to leave it runs for about 4 hours but nothing goes further.
Even reducing pool_opts.size = 2 I was not able to terminate thread test.s

TESTS

Testing Redis...
Pass sanity tests
Pass connection commands tests
Pass keys commands tests
Pass string commands tests
Pass list commands tests
Pass hash commands tests
Pass set commands tests
Pass zset commands tests
Pass hyperloglog commands tests
Pass geo commands tests
Pass script commands tests
Pass pubsub tests
Pass pipeline and transaction tests

Async Support

Are there plans to introduce async support anytime soon? Thanks!

Create Pipeline and Transaction with connection pool

So far, when creating Pipeline and Transaction, redis-plus-plus create a new connection to Redis server. Sometimes, it's a better idea to create these object with connection pool, i.e. avoid create creating an extra connection.

MinGW suseconds_t compile problem

Hi, I'm currently building redis-plus-plus with MinGW64.
I found an error while trying to compile connection.cpp, in particular the Connection::Connector::_to_timeval(const std::chrono::milliseconds &dur) function.
I had an undefined symbol to suseconds_t in static_cast<suseconds_t>(msec.count()). This is correct since I'm under windows and the winsock timeval is defined as:

typedef struct timeval {
long tv_sec;
long tv_usec;
} TIMEVAL, *PTIMEVAL, *LPTIMEVAL;

Is it possibile that you relate on the hideris timeval definition? Because, looking to the hiredis defines, I see guards for _MSC_VER which are probably not meet for MinGW.
Hover, I was able to fix this error by using WIN32 guards:

#ifdef WIN32

timeval Connection::Connector::_to_timeval(const std::chrono::milliseconds &dur) const {
    auto sec = std::chrono::duration_cast<std::chrono::seconds>(dur);
    auto msec = std::chrono::duration_cast<std::chrono::microseconds>(dur - sec);
    return {
        static_cast<long>(sec.count()),
        static_cast<long>(msec.count())
    };
}

#else

timeval Connection::Connector::_to_timeval(const std::chrono::milliseconds &dur) const {
    auto sec = std::chrono::duration_cast<std::chrono::seconds>(dur);
    auto msec = std::chrono::duration_cast<std::chrono::microseconds>(dur - sec);

    return {
            static_cast<std::time_t>(sec.count()),
            static_cast<suseconds_t>(msec.count())
    };
}

#endif

Is this change acceptable to you?
Thanks in advance

Are there any use cases?

We are finding a c++ redis client that supports cluster mode and password. Are there any online use cases of redis-plus-plus?

Create Redis object using ConnectionOptions in classes

Hi @sewenew ,
I would like to initialize a sw::redis::Redis obj in a class with a sw::redis::ConnectionOptions object.
Consider the following example:

using namespace sw:redis;

class MyClass
{
   public:
	MyClass() :
	   connection_options_(),
	   redis_(connection_options_)
	{}


   private:
	ConnectionOptions connection_options_;
	Redis redis_;

};

I would like to set connection_options_.socket_timeout and then pass the correct connection_options_ to redis_. Currently I'm not able to do that since ConnectionOption does not have a constructor which accepts this parameter. Moreover, it is not possibile to initialize ConnectionOption with an initialization list (something like {ConnectionType::TCP, "12.0.0.1", 6379, etc}). In addition, no default constructor for redis_ is define, so the only option I see here is to create a Redis* and manually allocate it. Something like:


using namespace sw:redis;

class MyClass
{
   public:
	MyClass() :
		connection_options_(),
		redis_(connection_options_)
		{
                        connection_options_.host = "127.0.0.1";
	                connection_options_.port = 6379;
			connection_options_.socket_timeout = std::chrono::seconds(1);
			redis_ = new Redis(connection_options_);
		}


   private:
	ConnectionOptions connection_options_;
	Redis* redis_;

};

Am I missing something?

Thanks in advance

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.