Fix handling of NIL invalidation messages.
When CLIENT TRACKING is enabled, Redis will send an invalidation message with a NIL payload to all tracking clients after a FLUSHDB is executed. We didn't account for REDIS_REPLY_PUSH being a valid parent object to a NIL payload, and were failing an assertion. Additionally this commit adds a regression test for the logic.
This commit is contained in:
parent
acc917548d
commit
b9b9f446fe
@ -257,7 +257,8 @@ static void *createNilObject(const redisReadTask *task) {
|
|||||||
parent = task->parent->obj;
|
parent = task->parent->obj;
|
||||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||||
parent->type == REDIS_REPLY_MAP ||
|
parent->type == REDIS_REPLY_MAP ||
|
||||||
parent->type == REDIS_REPLY_SET);
|
parent->type == REDIS_REPLY_SET ||
|
||||||
|
parent->type == REDIS_REPLY_PUSH);
|
||||||
parent->element[task->idx] = r;
|
parent->element[task->idx] = r;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
38
test.c
38
test.c
@ -53,6 +53,11 @@ struct privdata {
|
|||||||
int dtor_counter;
|
int dtor_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pushCounters {
|
||||||
|
int nil;
|
||||||
|
int str;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef HIREDIS_TEST_SSL
|
#ifdef HIREDIS_TEST_SSL
|
||||||
redisSSLContext *_ssl_ctx = NULL;
|
redisSSLContext *_ssl_ctx = NULL;
|
||||||
#endif
|
#endif
|
||||||
@ -677,11 +682,25 @@ static void test_blocking_connection_errors(void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dummy push handler */
|
/* Test push handler */
|
||||||
void push_handler(void *privdata, void *reply) {
|
void push_handler(void *privdata, void *r) {
|
||||||
int *counter = privdata;
|
struct pushCounters *pcounts = privdata;
|
||||||
|
redisReply *reply = r, *payload;
|
||||||
|
|
||||||
|
assert(reply && reply->type == REDIS_REPLY_PUSH && reply->elements == 2);
|
||||||
|
|
||||||
|
payload = reply->element[1];
|
||||||
|
if (payload->type == REDIS_REPLY_ARRAY) {
|
||||||
|
payload = payload->element[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload->type == REDIS_REPLY_STRING) {
|
||||||
|
pcounts->str++;
|
||||||
|
} else if (payload->type == REDIS_REPLY_NIL) {
|
||||||
|
pcounts->nil++;
|
||||||
|
}
|
||||||
|
|
||||||
freeReplyObject(reply);
|
freeReplyObject(reply);
|
||||||
*counter += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dummy function just to test setting a callback with redisOptions */
|
/* Dummy function just to test setting a callback with redisOptions */
|
||||||
@ -691,16 +710,16 @@ void push_handler_async(redisAsyncContext *ac, void *reply) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void test_resp3_push_handler(redisContext *c) {
|
static void test_resp3_push_handler(redisContext *c) {
|
||||||
|
struct pushCounters pc = {0};
|
||||||
redisPushFn *old = NULL;
|
redisPushFn *old = NULL;
|
||||||
redisReply *reply;
|
redisReply *reply;
|
||||||
void *privdata;
|
void *privdata;
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
/* Switch to RESP3 and turn on client tracking */
|
/* Switch to RESP3 and turn on client tracking */
|
||||||
send_hello(c, 3);
|
send_hello(c, 3);
|
||||||
send_client_tracking(c, "ON");
|
send_client_tracking(c, "ON");
|
||||||
privdata = c->privdata;
|
privdata = c->privdata;
|
||||||
c->privdata = &n;
|
c->privdata = &pc;
|
||||||
|
|
||||||
reply = redisCommand(c, "GET key:0");
|
reply = redisCommand(c, "GET key:0");
|
||||||
assert(reply != NULL);
|
assert(reply != NULL);
|
||||||
@ -717,7 +736,12 @@ static void test_resp3_push_handler(redisContext *c) {
|
|||||||
old = redisSetPushCallback(c, push_handler);
|
old = redisSetPushCallback(c, push_handler);
|
||||||
test("We can set a custom RESP3 PUSH handler: ");
|
test("We can set a custom RESP3 PUSH handler: ");
|
||||||
reply = redisCommand(c, "SET key:0 val:0");
|
reply = redisCommand(c, "SET key:0 val:0");
|
||||||
test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && n == 1);
|
test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && pc.str == 1);
|
||||||
|
freeReplyObject(reply);
|
||||||
|
|
||||||
|
test("We properly handle a NIL invalidation payload: ");
|
||||||
|
reply = redisCommand(c, "FLUSHDB");
|
||||||
|
test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && pc.nil == 1);
|
||||||
freeReplyObject(reply);
|
freeReplyObject(reply);
|
||||||
|
|
||||||
/* Unset the push callback and generate an invalidate message making
|
/* Unset the push callback and generate an invalidate message making
|
||||||
|
Loading…
Reference in New Issue
Block a user