diff --git a/Dockerfile.tests b/Dockerfile.tests new file mode 100644 index 0000000..24c4334 --- /dev/null +++ b/Dockerfile.tests @@ -0,0 +1,45 @@ +FROM debian:11 + +ENV RUBY_VERSION 2.7.2 +ENV BUNDLER_VERSION 1.16.6 + +ARG BRANCH=master +ENV REDIS_CLUSTER_PROXY_BRANCH ${BRANCH} + +RUN apt update && apt install -y procps curl wget gnupg2 lsb-release ca-certificates + +# Install REDIS +RUN curl -fsSL https://packages.redis.io/gpg | gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg +RUN echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/redis.list +RUN apt update && apt install -y redis + +# Install build essential +RUN apt install -y build-essential + +# clone project +RUN apt install -y git +WORKDIR / +RUN git clone https://github.com/domrod/redis-cluster-proxy.git +WORKDIR /redis-cluster-proxy +RUN git checkout ${REDIS_CLUSTER_PROXY_BRANCH} + +RUN make + +# Install ruby for tests +RUN curl -sSL https://rvm.io/mpapis.asc | gpg2 --import - +RUN curl -sSL https://rvm.io/pkuczynski.asc |gpg2 --import - +RUN curl -sSL https://get.rvm.io | bash -s stable +RUN /bin/bash -c "source /etc/profile.d/rvm.sh && \ + rvm install ${RUBY_VERSION} && \ + rvm use ${RUBY_VERSION} --default && \ + gem install bundler:${BUNDLER_VERSION}" + +ENTRYPOINT ["/bin/bash", "-c", "source /etc/profile.d/rvm.sh && \"$@\"", "-s"] + + + + + + + + diff --git a/Makefile b/Makefile index 3758a69..21f7516 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ test: $(MAKE) CFLAGS="-m32" LDFLAGS="-m32" valgrind: - $(MAKE) OPTIMIZATION="-O0" MALLOC="libc" + $(MAKE) OPTIMIZATION="-O3" MALLOC="libc" helgrind: - $(MAKE) OPTIMIZATION="-O0" MALLOC="libc" CFLAGS="-D__ATOMIC_VAR_FORCE_SYNC_MACROS" + $(MAKE) OPTIMIZATION="-O3" MALLOC="libc" CFLAGS="-D__ATOMIC_VAR_FORCE_SYNC_MACROS" diff --git a/src/cluster.c b/src/cluster.c index f50311e..1a7a55a 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -280,6 +280,7 @@ int resetCluster(redisCluster *cluster) { freeClusterNodes(cluster); cluster->slots_map = raxNew(); cluster->nodes_by_name = raxNew(); + cluster->master_names = NULL; cluster->nodes = listCreate(); if (!cluster->slots_map) return 0; if (!cluster->nodes) return 0; @@ -888,6 +889,13 @@ int updateCluster(redisCluster *cluster) { } cluster->is_updating = 0; cluster->update_required = 0; + /* Call once to refresh the master_names list */ + if (clusterGetMasterNames(cluster) == NULL) { + proxyLogErr("Failed to update master names after fetching cluster configuration! (thread: %d)", + cluster->thread_id); + status = CLUSTER_RECONFIG_ERR; + goto final; + } proxyLogDebug("Reprocessing cluster requests (thread: %d)", cluster->thread_id); while (raxNext(&iter)) { diff --git a/src/reply_order.c b/src/reply_order.c index df5d20e..c229df7 100644 --- a/src/reply_order.c +++ b/src/reply_order.c @@ -49,7 +49,7 @@ int appendUnorderedRepliesToBuffer(client *c) { uint64_t req_id = ntohu64(*((uint64_t *)iter.key)); if (req_id == c->min_reply_id) { sds reply = (sds) iter.data; - c->obuf = sdscat(c->obuf, reply); + c->obuf = sdscatsds(c->obuf, reply); c->min_reply_id++; count++; if (raxRemove(c->unordered_replies, iter.key, iter.key_len, NULL)){ diff --git a/src/sds.h b/src/sds.h index 1bdb60d..adcc12c 100644 --- a/src/sds.h +++ b/src/sds.h @@ -34,7 +34,7 @@ #define __SDS_H #define SDS_MAX_PREALLOC (1024*1024) -const char *SDS_NOINIT; +extern const char *SDS_NOINIT; #include #include diff --git a/src/version.h b/src/version.h index 4fed5dc..16f63cd 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define REDIS_CLUSTER_PROXY_VERSION "999.999.999" +#define REDIS_CLUSTER_PROXY_VERSION "1.0.1" diff --git a/test/tests/proxy_command.rb b/test/tests/proxy_command.rb index 3526073..ff0439a 100644 --- a/test/tests/proxy_command.rb +++ b/test/tests/proxy_command.rb @@ -5,7 +5,7 @@ 'threads' => 8, #'max-clients' => 10000 } - conf.each{|opt, val| + conf.each{|opt, val| reply = $main_proxy.proxy('config', 'get', opt.to_s) assert_not_redis_err(reply) assert(reply.is_a?(Array), "Expected array reply, got #{reply.class}") @@ -22,3 +22,32 @@ log = File.read $main_proxy.logfile assert_not_nil(log[msg], "Could not find logged message in proxy's log") end + +test "PROXY CLUSTER INFO" do + reply = $main_proxy.proxy('cluster', 'info') + assert_not_redis_err(reply) + assert(reply.is_a?(Array), "Expected array reply, got #{reply.class}") + assert(reply[0..4] == ["status", "updated", "connection", "shared", "nodes"], "Got unexpected reply: #{reply}") + reply[5].each{ |node| + _, name, _, ip, _, port, _, slots, _, replicas, _, connected = node + assert(ip == "127.0.0.1", "unexpected ip #{ip}") + assert([18000, 18001, 18002, 18003, 18004, 18005].include?(port), "unexpected port #{port}") + assert([5461, 5462].include?(slots), "unexpected slots #{slots}") + assert(replicas == 1, "replicas of #{replicas} != 1") + assert(connected == 1, "connected of #{connected} != 1") + } +end + +test "PROXY CLUSTER UPDATE" do + info_before = $main_proxy.proxy('cluster', 'info') + assert_not_redis_err(info_before) + + update_reply = $main_proxy.proxy('cluster', 'update') + assert_not_redis_err(update_reply) + + info_after = $main_proxy.proxy('cluster', 'info') + assert_not_redis_err(info_after) + + assert(info_before == info_after, "cluster info before update != cluster info after update.\n #{info_before} != #{info_after}") + +end