Giter Club home page Giter Club logo

Comments (2)

bjosv avatar bjosv commented on September 28, 2024

When using the regular API hiredis-cluster attempts to figure out which cluster node to send the command to
and currently it can't do that for MULTI since the command itself does not contain a key.
This means that redisClusterCommand() would fail when sending MULTI.
But, there is an alternative API which can be used to handle this, see existing tests for an example:

void test_transaction(redisClusterContext *cc) {
cluster_node *node = redisClusterGetNodeByKey(cc, "foo");
assert(node);
redisReply *reply;
reply = redisClusterCommandToNode(cc, node, "MULTI");
CHECK_REPLY_OK(cc, reply);
freeReplyObject(reply);
reply = redisClusterCommandToNode(cc, node, "SET foo 99");
CHECK_REPLY_QUEUED(cc, reply);
freeReplyObject(reply);
reply = redisClusterCommandToNode(cc, node, "INCR foo");
CHECK_REPLY_QUEUED(cc, reply);
freeReplyObject(reply);
reply = redisClusterCommandToNode(cc, node, "EXEC");
CHECK_REPLY_ARRAY(cc, reply, 2);
CHECK_REPLY_OK(cc, reply->element[0]);
CHECK_REPLY_INT(cc, reply->element[1], 100);
freeReplyObject(reply);
}

For async connections the above limitations currently also exists, but sending commands to a specific code will work in this case. See this testcase as an example (from the async-transaction-test branch not delivered to master yet):

void test_async_transaction() {
int status;
redisClusterAsyncContext *acc = redisClusterAsyncContextInit();
assert(acc);
redisClusterAsyncSetConnectCallback(acc, callbackExpectOk);
redisClusterAsyncSetDisconnectCallback(acc, callbackExpectOk);
redisClusterSetOptionAddNodes(acc->cc, CLUSTER_NODE);
redisClusterSetOptionMaxRetry(acc->cc, 1);
redisClusterSetOptionRouteUseSlots(acc->cc);
status = redisClusterConnect2(acc->cc);
ASSERT_MSG(status == REDIS_OK, acc->errstr);
struct event_base *base = event_base_new();
status = redisClusterLibeventAttach(acc, base);
assert(status == REDIS_OK);
cluster_node *node = redisClusterGetNodeByKey(acc->cc, "foo");
assert(node);
ExpectedResult r1 = {.type = REDIS_REPLY_STATUS, .str = "OK"};
status = redisClusterAsyncCommandToNode(acc, node, commandCallback, &r1,
"MULTI");
ASSERT_MSG(status == REDIS_OK, acc->errstr);
ExpectedResult r2 = {.type = REDIS_REPLY_STATUS, .str = "QUEUED"};
status = redisClusterAsyncCommandToNode(acc, node, commandCallback, &r2,
"SET foo 99");
ASSERT_MSG(status == REDIS_OK, acc->errstr);
ExpectedResult r3 = {.type = REDIS_REPLY_STATUS, .str = "QUEUED"};
status = redisClusterAsyncCommandToNode(acc, node, commandCallback, &r3,
"INCR foo");
ASSERT_MSG(status == REDIS_OK, acc->errstr);
/* The EXEC command will return an array with result from 2 queued commands. */
ExpectedResult r4 = {
.type = REDIS_REPLY_ARRAY, .elements = 2, .disconnect = true};
status = redisClusterAsyncCommandToNode(acc, node, commandCallback, &r4,
"EXEC ");
ASSERT_MSG(status == REDIS_OK, acc->errstr);
event_base_dispatch(base);
redisClusterAsyncFree(acc);
event_base_free(base);
}

from hiredis-cluster.

SS-TruMinds avatar SS-TruMinds commented on September 28, 2024

When using the regular API hiredis-cluster attempts to figure out which cluster node to send the command to and currently it can't do that for MULTI since the command itself does not contain a key. This means that redisClusterCommand() would fail when sending MULTI. But, there is an alternative API which can be used to handle this, see existing tests for an example:

void test_transaction(redisClusterContext *cc) {
cluster_node *node = redisClusterGetNodeByKey(cc, "foo");
assert(node);
redisReply *reply;
reply = redisClusterCommandToNode(cc, node, "MULTI");
CHECK_REPLY_OK(cc, reply);
freeReplyObject(reply);
reply = redisClusterCommandToNode(cc, node, "SET foo 99");
CHECK_REPLY_QUEUED(cc, reply);
freeReplyObject(reply);
reply = redisClusterCommandToNode(cc, node, "INCR foo");
CHECK_REPLY_QUEUED(cc, reply);
freeReplyObject(reply);
reply = redisClusterCommandToNode(cc, node, "EXEC");
CHECK_REPLY_ARRAY(cc, reply, 2);
CHECK_REPLY_OK(cc, reply->element[0]);
CHECK_REPLY_INT(cc, reply->element[1], 100);
freeReplyObject(reply);
}

For async connections the above limitations currently also exists, but sending commands to a specific code will work in this case. See this testcase as an example (from the async-transaction-test branch not delivered to master yet):

void test_async_transaction() {
int status;
redisClusterAsyncContext *acc = redisClusterAsyncContextInit();
assert(acc);
redisClusterAsyncSetConnectCallback(acc, callbackExpectOk);
redisClusterAsyncSetDisconnectCallback(acc, callbackExpectOk);
redisClusterSetOptionAddNodes(acc->cc, CLUSTER_NODE);
redisClusterSetOptionMaxRetry(acc->cc, 1);
redisClusterSetOptionRouteUseSlots(acc->cc);
status = redisClusterConnect2(acc->cc);
ASSERT_MSG(status == REDIS_OK, acc->errstr);
struct event_base *base = event_base_new();
status = redisClusterLibeventAttach(acc, base);
assert(status == REDIS_OK);
cluster_node *node = redisClusterGetNodeByKey(acc->cc, "foo");
assert(node);
ExpectedResult r1 = {.type = REDIS_REPLY_STATUS, .str = "OK"};
status = redisClusterAsyncCommandToNode(acc, node, commandCallback, &r1,
"MULTI");
ASSERT_MSG(status == REDIS_OK, acc->errstr);
ExpectedResult r2 = {.type = REDIS_REPLY_STATUS, .str = "QUEUED"};
status = redisClusterAsyncCommandToNode(acc, node, commandCallback, &r2,
"SET foo 99");
ASSERT_MSG(status == REDIS_OK, acc->errstr);
ExpectedResult r3 = {.type = REDIS_REPLY_STATUS, .str = "QUEUED"};
status = redisClusterAsyncCommandToNode(acc, node, commandCallback, &r3,
"INCR foo");
ASSERT_MSG(status == REDIS_OK, acc->errstr);
/* The EXEC command will return an array with result from 2 queued commands. */
ExpectedResult r4 = {
.type = REDIS_REPLY_ARRAY, .elements = 2, .disconnect = true};
status = redisClusterAsyncCommandToNode(acc, node, commandCallback, &r4,
"EXEC ");
ASSERT_MSG(status == REDIS_OK, acc->errstr);
event_base_dispatch(base);
redisClusterAsyncFree(acc);
event_base_free(base);
}

Understood. Thank you for the support.

from hiredis-cluster.

Related Issues (20)

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.