Skip to content

Commit b36f73c

Browse files
authored
Merge pull request #331 from codecrafters-io/extract-stage-descriptions
Extract stage descriptions to markdown files
2 parents 517704a + 28cdd27 commit b36f73c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+3206
-3264
lines changed

course-definition.yml

Lines changed: 9 additions & 3264 deletions
Large diffs are not rendered by default.

stage_descriptions/base-01-jm1.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
In this stage, you'll implement a TCP server that listens on port 6379.
2+
3+
[TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) is the underlying protocol used by protocols like HTTP, SSH and others
4+
you're probably familiar with. Redis clients & servers use TCP to communicate with each other.
5+
6+
Don't worry if you're unfamiliar with the TCP protocol, or what Redis clients & servers are. You'll learn more about this in the
7+
next stages.
8+
9+
### Tests
10+
11+
The tester will execute your program like this:
12+
13+
```bash
14+
$ ./your_program.sh
15+
```
16+
17+
It'll then try to connect to your TCP server on port 6379. If the connection succeeds, you'll pass this stage.
18+
19+
### Notes
20+
21+
- 6379 is the default port that Redis uses.
22+
- If you already have a Redis server running on your machine and listening on port 6379, you'll see a "port already in use" error when running your code. Try stopping the existing Redis server and running your code again.
23+
24+
{{#reader_is_bot}}
25+
- In this stage, you can assume that you only need to handle a single client. We'll get to handling multiple clients & multiple requests per client in later stages.
26+
{{/reader_is_bot}}

stage_descriptions/base-02-rg2.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
In this stage, you'll implement support for the [PING](https://redis.io/commands/ping) command.
2+
3+
Redis clients communicate with Redis servers by sending "[commands](https://redis.io/commands/)". For each command, a Redis server sends a response back to the client.
4+
Commands and responses are both encoded using the [Redis protocol](https://redis.io/topics/protocol) (we'll learn more about this in later stages).
5+
6+
[PING](https://redis.io/commands/ping/) is one of the simplest Redis commands. It's used to check whether a Redis server is healthy.
7+
8+
The response for the `PING` command is `+PONG\r\n`. This is the string "PONG" encoded using the [Redis protocol](https://redis.io/docs/reference/protocol-spec/).
9+
10+
In this stage, we'll cut corners by ignoring client input and hardcoding `+PONG\r\n` as a response. We'll learn to parse client input in later stages.
11+
12+
### Tests
13+
14+
The tester will execute your program like this:
15+
16+
```bash
17+
$ ./your_program.sh
18+
```
19+
20+
It'll then send a `PING` command to your server and expect a `+PONG\r\n` response.
21+
22+
```bash
23+
$ redis-cli PING
24+
```
25+
26+
Your server should respond with `+PONG\r\n`, which is "PONG" encoded as a [RESP simple string](https://redis.io/docs/reference/protocol-spec/#resp-simple-strings).
27+
28+
### Notes
29+
30+
- You can ignore the data that the tester sends you for this stage. We'll get to parsing
31+
client input in later stages. For now, you can just hardcode `+PONG\r\n` as the response.
32+
- You can also ignore handling multiple clients and handling multiple PING commands in the stage, we'll get to that in later stages.
33+
- The exact bytes your program will receive won't be just `PING`, you'll receive something like this: `*1\r\n$4\r\nPING\r\n`,
34+
which is the Redis protocol encoding of the `PING` command. We'll learn more about this in later stages.

stage_descriptions/base-03-wy1.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
In this stage, you'll respond to multiple
2+
[PING](https://redis.io/commands/ping) commands sent by the same connection.
3+
4+
A Redis server starts to listen for the next command as soon as it's done responding to the previous one. This allows
5+
Redis clients to send multiple commands using the same connection.
6+
7+
### Tests
8+
9+
The tester will execute your program like this:
10+
11+
```bash
12+
$ ./your_program.sh
13+
```
14+
15+
It'll then send multiple PING commands using the same connection. For example, it might send:
16+
17+
```bash
18+
$ echo -e "PING\nPING" | redis-cli
19+
```
20+
21+
The tester will expect to receive multiple `+PONG\r\n` responses (one for each command sent).
22+
23+
{{#lang_is_javascript}}
24+
In most languages, you'd need to run a loop that reads input from a connection and sends a
25+
response back. In JavaScript however, if you're listening to the
26+
[`data`](https://nodejs.org/api/net.html#net_event_data) event, this should be automatically handled for you. **It
27+
is very likely that the code you had for the previous stage will pass this stage without any changes!**
28+
{{/lang_is_javascript}}
29+
30+
{{^lang_is_javascript}}
31+
You'll need to run a loop that reads input from a connection and sends a
32+
response back.
33+
{{/lang_is_javascript}}
34+
35+
### Notes
36+
37+
- Just like the previous stage, you can hardcode `+PONG\r\n` as the response for this stage. We'll get to parsing
38+
client input in later stages.
39+
- The PING commands will be sent using the same connection. We'll get to handling multiple connections in later stages.

stage_descriptions/base-04-zu2.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
In this stage, you'll add support for multiple concurrent clients.
2+
3+
In addition to handling multiple commands from the same client, Redis servers are also designed to handle multiple clients at once.
4+
5+
{{#lang_is_javascript}}
6+
In most languages, you'd need to either use threads or implement an
7+
[Event Loop](https://en.wikipedia.org/wiki/Event_loop) to do this. In JavaScript however, since [the concurrency
8+
model itself is based on an event loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop), most
9+
standard library functions are designed to support this kind of concurrent behaviour out of the box. **It is very
10+
likely that the code you had for the previous stage will pass this stage without any changes!**
11+
{{/lang_is_javascript}}
12+
13+
{{^lang_is_javascript}}
14+
To implement this, you'll need to either use threads, or, if you're feeling
15+
adventurous, an [Event Loop](https://en.wikipedia.org/wiki/Event_loop) (like
16+
the official Redis implementation does).
17+
{{/lang_is_javascript}}
18+
19+
### Tests
20+
21+
The tester will execute your program like this:
22+
23+
```bash
24+
$ ./your_program.sh
25+
```
26+
27+
It'll then send two PING commands concurrently using two different connections:
28+
29+
```bash
30+
# These two will be sent concurrently so that we test your server's ability to handle concurrent clients.
31+
$ redis-cli PING
32+
$ redis-cli PING
33+
```
34+
35+
The tester will expect to receive two `+PONG\r\n` responses.
36+
37+
### Notes
38+
39+
- Since the tester client _only_ sends the PING command at the moment, it's okay to
40+
ignore what the client sends and hardcode a response. We'll get to parsing
41+
client input in later stages.

stage_descriptions/base-05-qq0.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
In this stage, you'll add support for the [ECHO](https://redis.io/commands/echo) command.
2+
3+
`ECHO` is a command like `PING` that's used for testing and debugging. It accepts a single argument and returns it back as a
4+
RESP bulk string.
5+
6+
```bash
7+
$ redis-cli PING # The command you implemented in previous stages
8+
PONG
9+
$ redis-cli ECHO hey # The command you'll implement in this stage
10+
hey
11+
```
12+
13+
### Tests
14+
15+
The tester will execute your program like this:
16+
17+
```bash
18+
$ ./your_program.sh
19+
```
20+
21+
It'll then send an `ECHO` command with an argument to your server:
22+
23+
```bash
24+
$ redis-cli ECHO hey
25+
```
26+
27+
The tester will expect to receive `$3\r\nhey\r\n` as a response (that's the string `hey` encoded as a [RESP bulk string](https://redis.io/docs/reference/protocol-spec/#bulk-strings).
28+
29+
### Notes
30+
31+
- We suggest that you implement a proper Redis protocol parser in this stage. It'll come in handy in later stages.
32+
- Redis command names are case-insensitive, so `ECHO`, `echo` and `EcHo` are all valid commands.
33+
- The tester will send a random string as an argument to the `ECHO` command, so you won't be able to hardcode the response to pass this stage.
34+
- The exact bytes your program will receive won't be just `ECHO hey`, you'll receive something like this: `*2\r\n$4\r\nECHO\r\n$3\r\nhey\r\n`. That's
35+
`["ECHO", "hey"]` encoded using the [Redis protocol](https://redis.io/docs/reference/protocol-spec/).
36+
- You can read more about how "commands" are handled in the Redis protocol [here](https://redis.io/docs/reference/protocol-spec/#sending-commands-to-a-redis-server).

stage_descriptions/base-06-la7.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
In this stage, you'll add support for the [SET](https://redis.io/commands/set) &
2+
[GET](https://redis.io/commands/get) commands.
3+
4+
The `SET` command is used to set a key to a value. The `GET` command is used to retrieve the value of a key.
5+
6+
```bash
7+
$ redis-cli SET foo bar
8+
OK
9+
$ redis-cli GET foo
10+
bar
11+
```
12+
13+
The `SET` command supports a number of extra options like `EX` (expiry time in seconds), `PX` (expiry time in milliseconds) and more. We
14+
won't cover these extra options in this stage. We'll get to them in later stages.
15+
16+
### Tests
17+
18+
The tester will execute your program like this:
19+
20+
```bash
21+
./your_program.sh
22+
```
23+
24+
It'll then send a `SET` command to your server:
25+
26+
```bash
27+
$ redis-cli SET foo bar
28+
```
29+
30+
The tester will expect to receive `+OK\r\n` as a response (that's the string `OK` encoded as a [RESP simple string](https://redis.io/docs/reference/protocol-spec/#resp-simple-strings)).
31+
32+
This command will be followed by a `GET` command:
33+
34+
```bash
35+
$ redis-cli GET foo
36+
```
37+
38+
The tester will expect to receive `$3\r\nbar\r\n` as a response (that's the string `bar` encoded as a [RESP bulk string](https://redis.io/docs/reference/protocol-spec/#bulk-strings).
39+
40+
### Notes
41+
42+
- If you implemented a proper Redis protocol parser in the previous stage, you should be able to reuse it in this stage.
43+
- Just like the previous stage, the values used for keys and values will be random, so you won't be able to hardcode the response to pass this stage.
44+
- If a key doesn't exist, the `GET` command should return a "null bulk string" (`$-1\r\n`). We won't explicitly test this in this stage, but you'll need it for the next stage (expiry).

stage_descriptions/base-07-yz1.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
In this stage, you'll add support for setting a key with an expiry.
2+
3+
The expiry for a key can be provided using the "PX" argument to the [SET](https://redis.io/commands/set) command. The expiry is provided in milliseconds.
4+
5+
```bash
6+
$ redis-cli SET foo bar px 100 # Sets the key "foo" to "bar" with an expiry of 100 milliseconds
7+
OK
8+
```
9+
10+
After the key has expired, a `GET` command for that key should return a "null bulk string" (`$-1\r\n`).
11+
12+
{{#lang_is_haskell}}
13+
The [time](https://hackage.haskell.org/package/time) package is available
14+
to use as a dependency.
15+
{{/lang_is_haskell}}
16+
17+
### Tests
18+
19+
The tester will execute your program like this:
20+
21+
```bash
22+
$ ./your_program.sh
23+
```
24+
25+
It'll then send a `SET` command to your server to set a key with an expiry:
26+
27+
```bash
28+
$ redis-cli SET foo bar px 100
29+
```
30+
31+
It'll then immediately send a `GET` command to retrieve the value:
32+
33+
```bash
34+
$ redis-cli GET foo
35+
```
36+
37+
It'll expect the response to be `bar` (encoded as a RESP bulk string).
38+
39+
It'll then wait for the key to expire and send another `GET` command:
40+
41+
```bash
42+
$ sleep 0.2 && redis-cli GET foo
43+
```
44+
45+
It'll expect the response to be `$-1\r\n` (a "null bulk string").
46+
47+
### Notes
48+
49+
- Just like command names, command arguments are also case-insensitive. So `PX`, `px` and `pX` are all valid.
50+
- The keys, values and expiry times used in the tests will be random, so you won't be able to hardcode a response to pass this stage.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)