Skip to content

Commit 003dfb1

Browse files
authored
Merge pull request #424 from codecrafters-io/TropicolX-patch-69
Revise "ACKs with commands #yd3" (stage 57)
2 parents cd7afb5 + 96cf25c commit 003dfb1

File tree

1 file changed

+33
-42
lines changed

1 file changed

+33
-42
lines changed
Lines changed: 33 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,29 @@
11
In this stage, you'll extend your `REPLCONF GETACK` implementation to respond with the number of bytes of commands processed by the replica.
22

3+
### ACKs (Recap)
4+
5+
As a recap, a master uses ACKs to verify that its replicas are in sync with it and haven't fallen behind. Each ACK contains an offset — the number of bytes of commands processed by the replica.
6+
37
### Offset tracking
48

5-
<details>
6-
<summary>Click to expand/collapse</summary>
7-
As we saw in previous stages, when a replica receives a command from the master, it processes it and updates its state. In addition to processing commands, the replica also keeps a running count of the number of bytes of commands it has processed.
8-
9-
This count is called the "offset". When a master sends a `REPLCONF GETACK` command to a replica, the replica is expected to respond with `REPLCONF ACK <offset>`. The returned `<offset>` should only include the number of bytes of commands processed **before** receiving the `REPLCONF GETACK` command.
10-
11-
As an example:
12-
13-
- Let's say a replica connects to a master and completes the handshake.
14-
- The master then sends a `REPLCONF GETACK *` command.
15-
- The replica should respond with `REPLCONF ACK 0`.
16-
- The returned offset is 0 since no commands have been processed yet (before receiving the `REPLCONF GETACK` command)
17-
- The master then sends `REPLCONF GETACK *` again.
18-
- The replica should respond with `REPLCONF ACK 37`.
19-
- The returned offset is 37 since the first `REPLCONF GETACK` command was processed, and it was 37 bytes long.
20-
- The RESP encoding for the `REPLCONF GETACK` command looks like this: `*3\r\n$8\r\nreplconf\r\n$6\r\ngetack\r\n$1\r\n*\r\n` (that's 37 bytes long)
21-
- The master then sends a `PING` command to the replica (masters do this periodically to notify replicas that the master is still alive).
22-
- The replica must silently process the `PING` command and update its offset. It should not send a response back to the master.
23-
- The master then sends `REPLCONF GETACK *` again (this is the third REPLCONF GETACK command received by the replica)
24-
- The replica should respond with `REPLCONF ACK 88`.
25-
- The returned offset is 88 (37 + 37 + 14)
26-
- 37 for the first `REPLCONF GETACK` command
27-
- 37 for the second `REPLCONF GETACK` command
28-
- 14 for the `PING` command
29-
- Note that the third `REPLCONF GETACK` command is not included in the offset, since the value should
30-
only include the number of bytes of commands processed **before** receiving the current `REPLCONF GETACK` command.
31-
- ... and so on
32-
33-
</details>
9+
A replica keeps its offset updated by tracking the total byte size of every command received from its master. This includes both write commands (like `SET`, `DEL`) and non-write commands (like `PING`, `REPLCONF GETACK *`).
10+
11+
After processing the received command (e.g., `["SET", "foo", "bar]`), it adds the full RESP array byte length to its running offset.
12+
13+
An important rule for this process is that the offset should only include commands processed **before** the current `REPLCONF GETACK *` request.
14+
15+
For example:
16+
17+
- A replica connects, completes the handshake, and the master sends `REPLCONF GETACK *`.
18+
- The replica responds with `REPLCONF ACK 0` since no commands had been processed before this request.
19+
- Next, the master sends another `REPLCONF GETACK *`.
20+
- The replica responds with `REPLCONF ACK 37`, because the previous `REPLCONF` command consumed 37 bytes.
21+
- The master then sends a `PING` command.
22+
- The replica silently processes it, increments its offset by 14, and sends no response.
23+
- The next `REPLCONF GETACK *` arrives.
24+
- The replica responds with `REPLCONF ACK 88` — that’s 37 (for the first `REPLCONF`), +37 (for the second `REPLCONF`), +14 (for the `PING`).
25+
26+
Notice that the current `GETACK` request itself is not included in the offset value.
3427

3528
### Tests
3629

@@ -45,23 +38,21 @@ Just like in the previous stages, your replica should complete the handshake wit
4538
The master will then propagate a series of commands to your replica. These commands will be interleaved with `REPLCONF GETACK *` commands.
4639

4740
```bash
48-
REPLCONF getack * # expecting REPLCONF ACK 0, since 0 bytes have been processed
41+
REPLCONF GETACK * # expect: REPLCONF ACK 0
4942

50-
ping # master sending a ping command to notify the replica that it's still alive
51-
REPLCONF getack * # expecting REPLCONF ACK 51
52-
# 51 = 37 (for the first REPLCONF command) + 14 (for the ping command)
43+
PING # replica processes silently
44+
REPLCONF GETACK * # expect: REPLCONF ACK 51
45+
# 51 = 37 (first REPLCONF) + 14 (PING)
5346

54-
set foo 1 # propagated from master to replica
55-
set bar 2 # propagated from master to replica
56-
REPLCONF getack * # expecting REPLCONF ACK 146
57-
# 146 = 51 + 37 (for the second REPLCONF command) + 29 (for the first set command) + 29 (for the second set command)
47+
SET foo 1 # replica processes silently
48+
SET bar 2 # replica processes silently
49+
REPLCONF GETACK * # expect: REPLCONF ACK 146
50+
# 146 = 51 + 37 (second REPLCONF) + 29 (SET foo) + 29 (SET bar)
5851
```
5952

53+
Your replica must calculate and return the exact offset at each step in the `REPLCONF ACK <offset>` response. Your response should also be encoded as a [RESP array](https://redis.io/docs/latest/develop/reference/protocol-spec/#arrays).
54+
6055
### Notes
6156

6257
- The offset should only include the number of bytes of commands processed **before** receiving the current `REPLCONF GETACK` command.
63-
- Although masters don't propagate `PING` commands when received from clients (since they aren't "write" commands),
64-
they may send `PING` commands to replicas to notify replicas that the master is still alive.
65-
- Replicas should update their offset to account for **all** commands propagated from the master, including `PING` and `REPLCONF` itself.
66-
- The response should be encoded as a [RESP Array](https://redis.io/docs/latest/develop/reference/protocol-spec/#arrays), like
67-
this: `*3\r\n$8\r\nREPLCONF\r\n$3\r\nACK\r\n$3\r\n154\r\n`.
58+
- Although masters don't propagate `PING` commands when received from clients (since they aren't "write" commands), they may send `PING` commands to replicas to notify replicas that the master is still alive.

0 commit comments

Comments
 (0)