Hi Dev,
I am stuck at stage: WAIT with multiple commands #na2. I’m not sure how to handle the the replicas who don’t respond with ACk.
I’ve attached logs and the relevant methods below. You can find the full source code here.
[tester::#NA2] Running tests for Stage #NA2 (Replication - WAIT with multiple commands)
[tester::#NA2] $ ./your_program.sh --port 6379
[tester::#NA2] Proceeding to create 3 replicas.
[tester::#NA2] [setup] Creating 3 replicas:
[tester::#NA2] [setup] 1. replica@6380 (Listening port = 6380)
[tester::#NA2] [setup] 2. replica@6381 (Listening port = 6381)
[tester::#NA2] [setup] 3. replica@6382 (Listening port = 6382)
[tester::#NA2] Creating replica@6380
[your_program] Redis server started on port 6379
[your_program] Running as master
[tester::#NA2] [handshake] [replica@6380] $ redis-cli PING
[tester::#NA2] [handshake] [replica@6380] Sent bytes: "*1\r\n$4\r\nPING\r\n"
[tester::#NA2] [handshake] [replica@6380] Received bytes: "+PONG\r\n"
[tester::#NA2] [handshake] [replica@6380] Received RESP simple string: "PONG"
[tester::#NA2] [handshake] [replica@6380] Received "PONG"
[tester::#NA2] [handshake] [replica@6380] > REPLCONF listening-port 6380
[tester::#NA2] [handshake] [replica@6380] Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n"
[your_program] Handling REPLCONF command: listening-port 6380
[your_program] Added replica on port 6380. Total replicas: 1
[tester::#NA2] [handshake] [replica@6380] Received bytes: "+OK\r\n"
[tester::#NA2] [handshake] [replica@6380] Received RESP simple string: "OK"
[tester::#NA2] [handshake] [replica@6380] Received "OK"
[tester::#NA2] [handshake] [replica@6380] > REPLCONF capa psync2
[tester::#NA2] [handshake] [replica@6380] Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n"
[tester::#NA2] [handshake] [replica@6380] Received bytes: "+OK\r\n"
[tester::#NA2] [handshake] [replica@6380] Received RESP simple string: "OK"
[your_program] Handling REPLCONF command: capa psync2
[tester::#NA2] [handshake] [replica@6380] Received "OK"
[tester::#NA2] [handshake] [replica@6380] > PSYNC ? -1
[tester::#NA2] [handshake] [replica@6380] Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n"
[tester::#NA2] [handshake] [replica@6380] Received bytes: "+FULLRESYNC 8371b4fb1155b71f4a04d3e1bc3e18c4a990aeeb 0\r\n"
[tester::#NA2] [handshake] [replica@6380] Received RESP simple string: "FULLRESYNC 8371b4fb1155b71f4a04d3e1bc3e18c4a990aeeb 0"
[tester::#NA2] [handshake] [replica@6380] Received "FULLRESYNC 8371b4fb1155b71f4a04d3e1bc3e18c4a990aeeb 0"
[tester::#NA2] [handshake] [replica@6380] Reading RDB file...
[tester::#NA2] [handshake] [replica@6380] Received bytes: "$88\r\nREDIS0011\xfa\tredis-ver\x057.2.0\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2m\b\xbce\xfa\bused-mem°\xc4\x10\x00\xfa\baof-base\xc0\x00\xff\xf0n;\xfe\xc0\xffZ\xa2"
[tester::#NA2] [handshake] [replica@6380] Received RDB file
[tester::#NA2] Creating replica@6381
[tester::#NA2] [handshake] [replica@6381] $ redis-cli PING
[tester::#NA2] [handshake] [replica@6381] Sent bytes: "*1\r\n$4\r\nPING\r\n"
[tester::#NA2] [handshake] [replica@6381] Received bytes: "+PONG\r\n"
[tester::#NA2] [handshake] [replica@6381] Received RESP simple string: "PONG"
[tester::#NA2] [handshake] [replica@6381] Received "PONG"
[tester::#NA2] [handshake] [replica@6381] > REPLCONF listening-port 6381
[tester::#NA2] [handshake] [replica@6381] Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6381\r\n"
[tester::#NA2] [handshake] [replica@6381] Received bytes: "+OK\r\n"
[tester::#NA2] [handshake] [replica@6381] Received RESP simple string: "OK"
[your_program] Handling REPLCONF command: listening-port 6381
[your_program] Added replica on port 6381. Total replicas: 2
[tester::#NA2] [handshake] [replica@6381] Received "OK"
[tester::#NA2] [handshake] [replica@6381] > REPLCONF capa psync2
[tester::#NA2] [handshake] [replica@6381] Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n"
[tester::#NA2] [handshake] [replica@6381] Received bytes: "+OK\r\n"
[tester::#NA2] [handshake] [replica@6381] Received RESP simple string: "OK"
[your_program] Handling REPLCONF command: capa psync2
[tester::#NA2] [handshake] [replica@6381] Received "OK"
[tester::#NA2] [handshake] [replica@6381] > PSYNC ? -1
[tester::#NA2] [handshake] [replica@6381] Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n"
[tester::#NA2] [handshake] [replica@6381] Received bytes: "+FULLRESYNC 8371b4fb1155b71f4a04d3e1bc3e18c4a990aeeb 0\r\n"
[tester::#NA2] [handshake] [replica@6381] Received RESP simple string: "FULLRESYNC 8371b4fb1155b71f4a04d3e1bc3e18c4a990aeeb 0"
[tester::#NA2] [handshake] [replica@6381] Received "FULLRESYNC 8371b4fb1155b71f4a04d3e1bc3e18c4a990aeeb 0"
[tester::#NA2] [handshake] [replica@6381] Reading RDB file...
[tester::#NA2] [handshake] [replica@6381] Received bytes: "$88\r\nREDIS0011\xfa\tredis-ver\x057.2.0\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2m\b\xbce\xfa\bused-mem°\xc4\x10\x00\xfa\baof-base\xc0\x00\xff\xf0n;\xfe\xc0\xffZ\xa2"
[tester::#NA2] [handshake] [replica@6381] Received RDB file
[tester::#NA2] Creating replica@6382
[tester::#NA2] [handshake] [replica@6382] $ redis-cli PING
[tester::#NA2] [handshake] [replica@6382] Sent bytes: "*1\r\n$4\r\nPING\r\n"
[tester::#NA2] [handshake] [replica@6382] Received bytes: "+PONG\r\n"
[tester::#NA2] [handshake] [replica@6382] Received RESP simple string: "PONG"
[tester::#NA2] [handshake] [replica@6382] Received "PONG"
[tester::#NA2] [handshake] [replica@6382] > REPLCONF listening-port 6382
[tester::#NA2] [handshake] [replica@6382] Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6382\r\n"
[tester::#NA2] [handshake] [replica@6382] Received bytes: "+OK\r\n"
[tester::#NA2] [handshake] [replica@6382] Received RESP simple string: "OK"
[your_program] Handling REPLCONF command: listening-port 6382
[your_program] Added replica on port 6382. Total replicas: 3
[tester::#NA2] [handshake] [replica@6382] Received "OK"
[tester::#NA2] [handshake] [replica@6382] > REPLCONF capa psync2
[tester::#NA2] [handshake] [replica@6382] Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n"
[your_program] Handling REPLCONF command: capa psync2
[tester::#NA2] [handshake] [replica@6382] Received bytes: "+OK\r\n"
[tester::#NA2] [handshake] [replica@6382] Received RESP simple string: "OK"
[tester::#NA2] [handshake] [replica@6382] Received "OK"
[tester::#NA2] [handshake] [replica@6382] > PSYNC ? -1
[tester::#NA2] [handshake] [replica@6382] Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n"
[tester::#NA2] [handshake] [replica@6382] Received bytes: "+FULLRESYNC 8371b4fb1155b71f4a04d3e1bc3e18c4a990aeeb 0\r\n"
[tester::#NA2] [handshake] [replica@6382] Received RESP simple string: "FULLRESYNC 8371b4fb1155b71f4a04d3e1bc3e18c4a990aeeb 0"
[tester::#NA2] [handshake] [replica@6382] Received "FULLRESYNC 8371b4fb1155b71f4a04d3e1bc3e18c4a990aeeb 0"
[tester::#NA2] [handshake] [replica@6382] Reading RDB file...
[tester::#NA2] [handshake] [replica@6382] Received bytes: "$88\r\nREDIS0011\xfa\tredis-ver\x057.2.0\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2m\b\xbce\xfa\bused-mem°\xc4\x10\x00\xfa\baof-base\xc0\x00\xff\xf0n;\xfe\xc0\xffZ\xa2"
[tester::#NA2] [handshake] [replica@6382] Received RDB file
[tester::#NA2] [test] [client] $ redis-cli SET foo 123
[tester::#NA2] [test] [client] Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n"
[your_program] Command [SET, foo, 123] uses 31 bytes
[your_program] master offset: 31
[tester::#NA2] [test] [client] Received bytes: "+OK\r\n"
[tester::#NA2] [test] [client] Received RESP simple string: "OK"
[tester::#NA2] [test] [client] Received "OK"
[tester::#NA2] [test] [client] > WAIT 1 500
[tester::#NA2] [test] [client] Sent bytes: "*3\r\n$4\r\nWAIT\r\n$1\r\n1\r\n$3\r\n500\r\n"
[tester::#NA2] [test] Testing Replica: replica@6380
[tester::#NA2] [test] [replica@6380] Expecting "SET foo 123" to be propagated
[tester::#NA2] [test] [replica@6380] Received bytes: "*3\r\n+SET\r\n+foo\r\n+123\r\n"
[tester::#NA2] [test] [replica@6380] Received RESP array: ["SET", "foo", "123"]
[tester::#NA2] [test] [replica@6380] Received ["SET", "foo", "123"]
[tester::#NA2] [test] [replica@6380] Expecting "REPLCONF GETACK *" from Master
[tester::#NA2] [test] [replica@6380] Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n"
[tester::#NA2] [test] [replica@6380] Received RESP array: ["REPLCONF", "GETACK", "*"]
[tester::#NA2] [test] [replica@6380] Received ["REPLCONF", "GETACK", "*"]
[tester::#NA2] [test] [replica@6380] Sending ACK to Master
[tester::#NA2] [test] [replica@6380] > REPLCONF ACK 22
[tester::#NA2] [test] [replica@6380] Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$3\r\nACK\r\n$2\r\n22\r\n"
[tester::#NA2] [test] Testing Replica: replica@6381
[tester::#NA2] [test] [replica@6381] Expecting "SET foo 123" to be propagated
[tester::#NA2] [test] [replica@6381] Received bytes: "*3\r\n+SET\r\n+foo\r\n+123\r\n"
[tester::#NA2] [test] [replica@6381] Received RESP array: ["SET", "foo", "123"]
[tester::#NA2] [test] [replica@6381] Received ["SET", "foo", "123"]
[tester::#NA2] [test] [replica@6381] Expecting "REPLCONF GETACK *" from Master
[your_program] Handling REPLCONF command: ACK 22
[your_program] Received ACK from replica
[your_program] Replica acknowledged offset: 22, Master offset: 31
[tester::#NA2] [test] [replica@6381] Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n"
[tester::#NA2] [test] [replica@6381] Received RESP array: ["REPLCONF", "GETACK", "*"]
[tester::#NA2] [test] [replica@6381] Received ["REPLCONF", "GETACK", "*"]
[tester::#NA2] [test] [replica@6381] Not sending ACK to Master
[tester::#NA2] [test] Testing Replica: replica@6382
[tester::#NA2] [test] [replica@6382] Expecting "SET foo 123" to be propagated
[tester::#NA2] [test] [replica@6382] Received bytes: "*3\r\n+SET\r\n+foo\r\n+123\r\n"
[tester::#NA2] [test] [replica@6382] Received RESP array: ["SET", "foo", "123"]
[tester::#NA2] [test] [replica@6382] Received ["SET", "foo", "123"]
[tester::#NA2] [test] [replica@6382] Expecting "REPLCONF GETACK *" from Master
[tester::#NA2] [test] [replica@6382] Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n"
[tester::#NA2] [test] [replica@6382] Received RESP array: ["REPLCONF", "GETACK", "*"]
[tester::#NA2] [test] [replica@6382] Received ["REPLCONF", "GETACK", "*"]
[tester::#NA2] [test] [replica@6382] Not sending ACK to Master
[tester::#NA2] [test] [client] Received bytes: ":0\r\n"
[tester::#NA2] [test] [client] Received RESP integer: 0
[tester::#NA2] Expected 1, got 0
[tester::#NA2] Test failed
[tester::#NA2] Terminating program
[tester::#NA2] Program terminated successfully
public void handleReplconf(String clientId, List<String> command, OutputStream out) throws IOException {
if (command.size() < 3) {
writeError(RedisConstants.ERR_WRONG_NUMBER_ARGS + " 'REPLCONF' command", out);
return;
}
String arg1 = command.get(1);
String arg2 = command.get(2);
System.out.println("Handling REPLCONF command: " + arg1 + " " + arg2);
switch (arg1) {
case RedisConstants.LISTENING_PORT:
serverConfig.addReplica(out, Integer.parseInt(arg2));
writeSimpleString("OK", out);
break;
case RedisConstants.CAPABILITIES:
writeSimpleString("OK", out);
break;
case RedisConstants.GETACK:
String offset = String.valueOf(serverConfig.getReplicaOffset());
writeArray(3, out);
writeBulkString("REPLCONF", out);
writeBulkString("ACK", out);
writeBulkString(offset, out);
int bytes = RespProtocol.calculateRespCommandBytes(command);
serverConfig.setReplicaOffset(serverConfig.getReplicaOffset() + bytes);
System.out.println("getack: " + command + " replica offset: " + serverConfig.getReplicaOffset());
break;
case RedisConstants.ACK:
System.out.println("Received ACK from replica");
int receivedReplicaOffset = Integer.parseInt(arg2);
if(receivedReplicaOffset >= serverConfig.getMasterOffset()){
serverConfig.setUpToDateReplicas(serverConfig.getUpToDateReplicas() + 1);
}
System.out.println("Replica acknowledged offset: " + receivedReplicaOffset +
", Master offset: " + serverConfig.getMasterOffset());
break;
}
}
public void handleWait(String clientId, List<String> command, OutputStream out) throws IOException, InterruptedException {
if (command.size() < 3) {
writeError(RedisConstants.ERR_WRONG_NUMBER_ARGS + " 'WAIT' command", out);
return;
}
if(!serverConfig.hasReplicas()){
writeInteger(0, out);
return;
}
serverConfig.setUpToDateReplicas(0);
serverConfig.getAck();
int minimumUpToDateReplica = Integer.parseInt(command.get(1));
long duration = Long.parseLong(command.get(2));
long startTime = System.currentTimeMillis();
long endTime = startTime + duration;
while(System.currentTimeMillis() < endTime) {
if(serverConfig.getUpToDateReplicas() >= minimumUpToDateReplica) {
System.out.println("wait res sent: " + serverConfig.getUpToDateReplicas());
writeInteger(serverConfig.getUpToDateReplicas(), out);
return;
}
Thread.sleep(1);
}
writeInteger(serverConfig.getUpToDateReplicas(), out);
}
Would really appreciate your help!!
Thanks.

