summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/replication.c19
-rw-r--r--src/server.h2
-rw-r--r--tests/unit/wait.tcl70
3 files changed, 86 insertions, 5 deletions
diff --git a/src/replication.c b/src/replication.c
index 152980dc0..c5acced9d 100644
--- a/src/replication.c
+++ b/src/replication.c
@@ -3612,7 +3612,9 @@ void unblockClientWaitingReplicas(client *c) {
* since we received enough ACKs from slaves. */
void processClientsWaitingReplicas(void) {
long long last_offset = 0;
+ long long last_aof_offset = 0;
int last_numreplicas = 0;
+ int last_aof_numreplicas = 0;
listIter li;
listNode *ln;
@@ -3628,7 +3630,7 @@ void processClientsWaitingReplicas(void) {
if (is_wait_aof && c->bstate.numlocal && !server.aof_enabled) {
addReplyError(c, "WAITAOF cannot be used when numlocal is set but appendonly is disabled.");
unblockClient(c);
- return;
+ continue;
}
/* Every time we find a client that is satisfied for a given
@@ -3636,10 +3638,14 @@ void processClientsWaitingReplicas(void) {
* may be unblocked without calling replicationCountAcksByOffset()
* or calling replicationCountAOFAcksByOffset()
* if the requested offset / replicas were equal or less. */
- if (last_offset && last_offset >= c->bstate.reploffset &&
+ if (!is_wait_aof && last_offset && last_offset >= c->bstate.reploffset &&
last_numreplicas >= c->bstate.numreplicas)
{
numreplicas = last_numreplicas;
+ } else if (is_wait_aof && last_aof_offset && last_aof_offset >= c->bstate.reploffset &&
+ last_aof_numreplicas >= c->bstate.numreplicas)
+ {
+ numreplicas = last_aof_numreplicas;
} else {
numreplicas = is_wait_aof ?
replicationCountAOFAcksByOffset(c->bstate.reploffset) :
@@ -3648,8 +3654,13 @@ void processClientsWaitingReplicas(void) {
/* Check if the number of replicas is satisfied. */
if (numreplicas < c->bstate.numreplicas) continue;
- last_offset = c->bstate.reploffset;
- last_numreplicas = numreplicas;
+ if (is_wait_aof) {
+ last_aof_offset = c->bstate.reploffset;
+ last_aof_numreplicas = numreplicas;
+ } else {
+ last_offset = c->bstate.reploffset;
+ last_numreplicas = numreplicas;
+ }
}
/* Check if the local constraint of WAITAOF is served */
diff --git a/src/server.h b/src/server.h
index ed39b1b96..3b267cf2e 100644
--- a/src/server.h
+++ b/src/server.h
@@ -1009,7 +1009,7 @@ typedef struct blockingState {
/* BLOCKED_LIST, BLOCKED_ZSET and BLOCKED_STREAM or any other Keys related blocking */
dict *keys; /* The keys we are blocked on */
- /* BLOCKED_WAIT */
+ /* BLOCKED_WAIT and BLOCKED_WAITAOF */
int numreplicas; /* Number of replicas we are waiting for ACK. */
int numlocal; /* Indication if WAITAOF is waiting for local fsync. */
long long reploffset; /* Replication offset to reach. */
diff --git a/tests/unit/wait.tcl b/tests/unit/wait.tcl
index 8990965d5..08a7a71f6 100644
--- a/tests/unit/wait.tcl
+++ b/tests/unit/wait.tcl
@@ -360,3 +360,73 @@ tags {"wait aof network external:skip"} {
}
}
}
+
+start_server {tags {"failover external:skip"}} {
+start_server {} {
+start_server {} {
+ set master [srv 0 client]
+ set master_host [srv 0 host]
+ set master_port [srv 0 port]
+
+ set replica1 [srv -1 client]
+ set replica1_pid [srv -1 pid]
+
+ set replica2 [srv -2 client]
+
+ test {setup replication for following tests} {
+ $replica1 replicaof $master_host $master_port
+ $replica2 replicaof $master_host $master_port
+ wait_for_sync $replica1
+ wait_for_sync $replica2
+ }
+
+ test {WAIT and WAITAOF replica multiple clients unblock - reuse last result} {
+ set rd [redis_deferring_client]
+ set rd2 [redis_deferring_client]
+
+ $master config set appendonly yes
+ $replica1 config set appendonly yes
+ $replica2 config set appendonly yes
+
+ $master config set appendfsync always
+ $replica1 config set appendfsync no
+ $replica2 config set appendfsync no
+
+ waitForBgrewriteaof $master
+ waitForBgrewriteaof $replica1
+ waitForBgrewriteaof $replica2
+
+ exec kill -SIGSTOP $replica1_pid
+
+ $rd incr foo
+ $rd read
+ $rd waitaof 0 1 0
+
+ # rd2 has a newer repl_offset
+ $rd2 incr foo
+ $rd2 read
+ $rd2 wait 2 0
+
+ wait_for_blocked_clients_count 2
+
+ exec kill -SIGCONT $replica1_pid
+
+ # WAIT will unblock the client first.
+ assert_equal [$rd2 read] {2}
+
+ # Make $replica1 catch up the repl_aof_off, then WAITAOF will unblock the client.
+ $replica1 config set appendfsync always
+ $master incr foo
+ assert_equal [$rd read] {1 1}
+
+ $rd ping
+ assert_equal [$rd read] {PONG}
+ $rd2 ping
+ assert_equal [$rd2 read] {PONG}
+
+ $rd close
+ $rd2 close
+ }
+}
+}
+}