I’m stuck on Stage #YG4.
It feels like the test master gives me no time to react to the first get command.
My Python code can succesfully finish the master handshake, and then use the same socket to receive set commands from the test master to update the replica db - even when e.g. multiple set commands are received at the same time. However, I keep getting errors with the first get command.
Unlike the set commands, I was completely incapable to receive the get command from the master handshake socket. First, I thought my code maybe was going through the set commands too slowly, and that this lead to timeouts. I made a function testing the socket after the master handshake completes. It simply “empties” the socket by receiving data until chunk size is not above 0. It does not process the set commands which I could get away with because the master does not expect responses to the set commands.
No matter what, the data received from the handshake socket did not include the get command. I then tried creating a new socket by using accept() with the replica server socket immediately after emptying the handshake socket. Now I was able to receive the get command - but it´s as if the test master does not wait for me to respond even though I try to make the code as fast as possible by cheating with the set commands. Immediately after receiving the get command from the new socket, I respond with a sendall hardcoded to send the expected answer to the get command without spending time on my actual get function extracting info from the replica db. No matter what, I keep getting the message that nothing is received immediately after being told that a get cmd request has been sent.
I don´t have a lot of experience with sockets. Is this expected behavior? I thought all the requests were supposed to be made with the handshake socket.
Here are my logs. The prints in test_socket don´t even all finish before tester terminates the program:
remote: [tester::#YG4] [handshake] master: Waiting for replica to initiate handshake with "PING" command
remote: [tester::#YG4] [handshake] master: Received bytes: "*1\r\n$4\r\nping\r\n"
remote: [tester::#YG4] [handshake] master: Received RESP array: ["ping"]
remote: [tester::#YG4] [handshake] Received ["ping"]
remote: [tester::#YG4] [handshake] master: Sent "PONG"
remote: [tester::#YG4] [handshake] master: Sent bytes: "+PONG\r\n"
remote: [tester::#YG4] [handshake] master: Waiting for replica to send "REPLCONF listening-port 6380" command
remote: [tester::#YG4] [handshake] master: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n"
remote: [tester::#YG4] [handshake] master: Received RESP array: ["REPLCONF", "listening-port", "6380"]
remote: [tester::#YG4] [handshake] Received ["REPLCONF", "listening-port", "6380"]
remote: [tester::#YG4] [handshake] master: Sent "OK"
remote: [tester::#YG4] [handshake] master: Sent bytes: "+OK\r\n"
remote: [tester::#YG4] [handshake] master: Waiting for replica to send "REPLCONF capa" command
remote: [tester::#YG4] [handshake] master: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n"
remote: [tester::#YG4] [handshake] master: Received RESP array: ["REPLCONF", "capa", "psync2"]
remote: [tester::#YG4] [handshake] Received ["REPLCONF", "capa", "psync2"]
remote: [tester::#YG4] [handshake] master: Sent "OK"
remote: [tester::#YG4] [handshake] master: Sent bytes: "+OK\r\n"
remote: [tester::#YG4] [handshake] master: Waiting for replica to send "PSYNC" command
remote: [tester::#YG4] [handshake] master: Received bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n"
remote: [tester::#YG4] [handshake] master: Received RESP array: ["PSYNC", "?", "-1"]
remote: [tester::#YG4] [handshake] Received ["PSYNC", "?", "-1"]
remote: [tester::#YG4] [handshake] master: Sent "FULLRESYNC 75cd7bc10c49047e0d163660f3b90625b1af31dc 0"
remote: [tester::#YG4] [handshake] master: Sent bytes: "+FULLRESYNC 75cd7bc10c49047e0d163660f3b90625b1af31dc 0\r\n"
remote: [tester::#YG4] [handshake] Sending RDB file...
remote: [tester::#YG4] [handshake] master: Sent 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"
remote: [tester::#YG4] [handshake] Sent RDB file.
remote: [tester::#YG4] [propagation] master: > SET foo 123
remote: [tester::#YG4] [propagation] master: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n"
remote: [tester::#YG4] [propagation] master: > SET bar 456
remote: [tester::#YG4] [propagation] master: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbar\r\n$3\r\n456\r\n"
remote: [tester::#YG4] [propagation] master: > SET baz 789
remote: [tester::#YG4] [propagation] master: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n"
remote: [tester::#YG4] [test] Getting key foo
remote: [tester::#YG4] [test] client: $ redis-cli GET foo
remote: [tester::#YG4] [test] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$3\r\nfoo\r\n"
remote: [your_program] Starting test_socket...
remote: [your_program] Emptying handshake_socket
remote: [tester::#YG4] Received: "" (no content received)
remote: [tester::#YG4] ^ error
remote: [tester::#YG4] Error: Expected start of a new RESP2 value (either +, -, :, $ or *)
remote: [tester::#YG4] Test failed
remote: [tester::#YG4] Terminating program
remote: [your_program] Command(s) received with handshake_socket: b'*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n*3\r\n$3\r\nSET\r\n$3\r\nbar\r\n$3\r\n456\r\n*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n'
remote: [your_program] Creating get_cmd_socket
remote: [your_program] Command(s) received with get_cmd_socket: b'*2\r\n$3\r\nGET\r\n$3\r\nfoo\r\n'
remote: [your_program] Sending response to get command
remote: [tester::#YG4] Program terminated successfully
And here’s a snippet of my code:
def test_socket(handshake_socket):
data = b""
while True:
chunk = handshake_socket.recv(4096)
if len(chunk) > 0:
data += chunk
else:
break
print(f"Command(s) received with handshake_socket: {data}")
set_cmd_socket, addr = server_socket.accept()
chunk = get_cmd_socket.recv(4096)
print(f"Command(s) received with get_cmd_socket: {chunk}")
get_cmd_socket.sendall("$3\r\n123\r\n").encode()