diff --git a/internal/redis_executable/redis_executable.go b/internal/redis_executable/redis_executable.go index acf1868..4a46f8a 100644 --- a/internal/redis_executable/redis_executable.go +++ b/internal/redis_executable/redis_executable.go @@ -30,7 +30,16 @@ func (b *RedisExecutable) Run(args ...string) error { if b.args == nil || len(b.args) == 0 { b.logger.Infof("$ ./spawn_redis_server.sh") } else { - b.logger.Infof("$ ./spawn_redis_server.sh %s", strings.Join(b.args, " ")) + var log string + log += "$ ./spawn_redis_server.sh" + for _, arg := range b.args { + if strings.Contains(arg, " ") { + log += " \"" + arg + "\"" + } else { + log += " " + arg + } + } + b.logger.Infof(log) } if err := b.executable.Start(b.args...); err != nil { diff --git a/internal/test_helpers/course_definition.yml b/internal/test_helpers/course_definition.yml index a1a06eb..631a26f 100644 --- a/internal/test_helpers/course_definition.yml +++ b/internal/test_helpers/course_definition.yml @@ -4,7 +4,7 @@ short_name: "Redis" release_status: "live" description_md: |- - Redis is an in-memory data structure store often used as a database, cache, message broken and streaming engine. In this challenge + Redis is an in-memory data structure store often used as a database, cache, message broker and streaming engine. In this challenge you'll build your own Redis server that is capable of serving basic commands, reading RDB files and more. Along the way, you'll learn about TCP servers, the Redis Protocol and more. @@ -22,6 +22,7 @@ languages: - slug: "crystal" - slug: "csharp" - slug: "elixir" + - slug: "gleam" - slug: "go" - slug: "haskell" - slug: "java" @@ -30,6 +31,10 @@ languages: - slug: "python" - slug: "ruby" - slug: "rust" + - slug: "typescript" + - slug: "scala" + release_status: "beta" + - slug: "zig" marketing: difficulty: medium @@ -87,7 +92,13 @@ extensions: stages: - slug: "init" concept_slugs: - ["network-protocols", "tcp-overview", "go-tcp-server", "rust-tcp-server"] + [ + "network-protocols", + "tcp-overview", + "go-tcp-server", + "rust-tcp-server", + "python-tcp-server", + ] name: "Bind to a port" description_md: |- In this stage, you'll implement a TCP server that listens on port 6379. @@ -120,7 +131,13 @@ stages: - slug: "ping-pong" concept_slugs: - ["network-protocols", "tcp-overview", "go-tcp-server", "rust-tcp-server"] + [ + "network-protocols", + "tcp-overview", + "go-tcp-server", + "rust-tcp-server", + "python-tcp-server", + ] name: "Respond to PING" difficulty: easy description_md: |- @@ -146,7 +163,7 @@ stages: It'll then send a `PING` command to your server and expect a `+PONG\r\n` response. ```bash - $ redis-cli ping + $ redis-cli PING ``` 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). @@ -156,7 +173,7 @@ stages: - You can ignore the data that the tester sends you for this stage. We'll get to parsing client input in later stages. For now, you can just hardcode `+PONG\r\n` as the response. - You can also ignore handling multiple clients and handling multiple PING commands in the stage, we'll get to that in later stages. - - 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`, + - 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`, which is the Redis protocol encoding of the `PING` command. We'll learn more about this in later stages. marketing_md: | In this stage, you'll respond to the @@ -166,7 +183,13 @@ stages: - slug: "ping-pong-multiple" concept_slugs: - ["network-protocols", "tcp-overview", "go-tcp-server", "rust-tcp-server"] + [ + "network-protocols", + "tcp-overview", + "go-tcp-server", + "rust-tcp-server", + "python-tcp-server", + ] name: "Respond to multiple PINGs" difficulty: easy description_md: |- @@ -187,7 +210,7 @@ stages: It'll then send two PING commands using the same connection: ```bash - $ echo -e "ping\nping" | redis-cli + $ echo -e "PING\nPING" | redis-cli ``` The tester will expect to receive two `+PONG\r\n` responses. @@ -216,7 +239,13 @@ stages: - slug: "concurrent-clients" concept_slugs: - ["network-protocols", "tcp-overview", "go-tcp-server", "rust-tcp-server"] + [ + "network-protocols", + "tcp-overview", + "go-tcp-server", + "rust-tcp-server", + "python-tcp-server", + ] name: "Handle concurrent clients" difficulty: medium description_md: |- @@ -250,8 +279,8 @@ stages: ```bash # These two will be sent concurrently so that we test your server's ability to handle concurrent clients. - $ redis-cli ping - $ redis-cli ping + $ redis-cli PING + $ redis-cli PING ``` The tester will expect to receive two `+PONG\r\n` responses. @@ -278,9 +307,9 @@ stages: RESP bulk string. ```bash - $ redis-cli ping # The command you implemented in previous stages + $ redis-cli PING # The command you implemented in previous stages PONG - $ redis-cli echo hey # The command you'll implement in this stage + $ redis-cli ECHO hey # The command you'll implement in this stage hey ``` @@ -295,7 +324,7 @@ stages: It'll then send an `ECHO` command with an argument to your server: ```bash - $ redis-cli echo hey + $ redis-cli ECHO hey ``` 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). @@ -305,8 +334,8 @@ stages: - We suggest that you implement a proper Redis protocol parser in this stage. It'll come in handy in later stages. - Redis command names are case-insensitive, so `ECHO`, `echo` and `EcHo` are all valid commands. - 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. - - 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 - `["echo", "hey"]` encoded using the [Redis protocol](https://redis.io/docs/reference/protocol-spec/). + - 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 + `["ECHO", "hey"]` encoded using the [Redis protocol](https://redis.io/docs/reference/protocol-spec/). - 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). marketing_md: |- In this stage, you'll respond to the @@ -326,9 +355,9 @@ stages: The `SET` command is used to set a key to a value. The `GET` command is used to retrieve the value of a key. ```bash - $ redis-cli set foo bar + $ redis-cli SET foo bar OK - $ redis-cli get foo + $ redis-cli GET foo bar ``` @@ -346,7 +375,7 @@ stages: It'll then send a `SET` command to your server: ```bash - $ redis-cli set foo bar + $ redis-cli SET foo bar ``` 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)). @@ -354,7 +383,7 @@ stages: This command will be followed by a `GET` command: ```bash - $ redis-cli get foo + $ redis-cli GET foo ``` 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). @@ -379,7 +408,7 @@ stages: 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. ```bash - $ redis-cli set foo bar px 100 # Sets the key "foo" to "bar" with an expiry of 100 milliseconds + $ redis-cli SET foo bar px 100 # Sets the key "foo" to "bar" with an expiry of 100 milliseconds OK ``` @@ -401,13 +430,13 @@ stages: It'll then send a `SET` command to your server to set a key with an expiry: ```bash - $ redis-cli set foo bar px 100 + $ redis-cli SET foo bar px 100 ``` It'll then immediately send a `GET` command to retrieve the value: ```bash - $ redis-cli get foo + $ redis-cli GET foo ``` It'll expect the response to be `bar` (encoded as a RESP bulk string). @@ -415,7 +444,7 @@ stages: It'll then wait for the key to expire and send another `GET` command: ```bash - $ sleep 0.2 && redis-cli get foo + $ sleep 0.2 && redis-cli GET foo ``` It'll expect the response to be `$-1\r\n` (a "null bulk string"). @@ -437,41 +466,67 @@ stages: name: "RDB file config" difficulty: easy description_md: | - Redis uses `.rdb` files for persistence. In this stage, you'll add support for reading the config values related to where RDB files are stored. + Welcome to the RDB Persistence Extension! In this extension, you'll add support for reading [RDB files](https://redis.io/docs/management/persistence/) (Redis Database files). + + In this stage, you'll add support for two configuration parameters related to RDB persistence, as well as the [CONFIG GET](https://redis.io/docs/latest/commands/config-get/) command. - There are two config values that determine where RDB files are stored: + ### RDB files - - `dir`: The directory where RDB files are stored - - `dbfilename`: The name of the RDB file + An RDB file is a point-in-time snapshot of a Redis dataset. When RDB persistence is enabled, the Redis server syncs its in-memory state with an RDB file, by doing the following: - These values will be passed into your program like this: + 1. On startup, the Redis server loads the data from the RDB file. + 2. While running, the Redis server periodically takes new snapshots of the dataset, in order to update the RDB file. + ### `dir` and `dbfilename` + + The configuration parameters `dir` and `dbfilename` specify where an RDB file is stored: + - `dir` - the path to the directory where the RDB file is stored (example: `/tmp/redis-data`) + - `dbfilename` - the name of the RDB file (example: `rdbfile`) + + ### The `CONFIG GET` command + + The [`CONFIG GET`](https://redis.io/docs/latest/commands/config-get/) command returns the values of configuration parameters. + + It takes in one or more configuration parameters and returns a [RESP array](https://redis.io/docs/latest/develop/reference/protocol-spec/#arrays) of key-value pairs: + + ```bash + $ redis-cli CONFIG GET dir + 1) "dir" + 2) "/tmp/redis-data" ``` + + Although `CONFIG GET` can fetch multiple parameters at a time, the tester will only send `CONFIG GET` commands with one parameter at a time. + + ### Tests + + The tester will execute your program like this: + + ```bash ./spawn_redis_server.sh --dir /tmp/redis-files --dbfilename dump.rdb ``` - To verify whether your program is reading config values correctly, the tester will send you two commands: + It'll then send the following commands: ```bash - redis-cli CONFIG GET dir - redis-cli CONFIG GET dbfilename + $ redis-cli CONFIG GET dir + $ redis-cli CONFIG GET dbfilename ``` - The response to `CONFIG GET ` should be a RESP array with two elements: the key and the value. + Your server must respond to each `CONFIG GET` command with a RESP array containing two elements: - For example, let's say the `dir` value is `/tmp/redis-files`. The expected response will be: + 1. The parameter **name**, encoded as a [RESP Bulk string](https://redis.io/docs/latest/develop/reference/protocol-spec/#bulk-strings) + 2. The parameter **value**, encoded as a RESP Bulk string - ``` + For example, if the value of `dir` is `/tmp/redis-files`, then the expected response to `CONFIG GET dir` is: + + ```bash *2\r\n$3\r\ndir\r\n$16\r\n/tmp/redis-files\r\n ``` - - `*2\r\n` indicates that the array has two elements - - `$3\r\ndir\r\n` indicates that the first element is a bulk string with the value `dir` - - `$16\r\n/tmp/redis-files\r\n` indicates that the second element is a bulk string with the value `/tmp/redis-files` + ### Notes - **Note**: If your repository was created before 5th Oct 2023, it's possible that your `./spawn_redis_server.sh` script - might not be passing arguments on to your program. You'll need to edit `./spawn_redis_server.sh` to fix this, check - [this PR](https://github.com/codecrafters-io/build-your-own-redis/pull/89/files) for details. + 1. You don't need to read the RDB file in this stage, you only need to store `dir` and `dbfilename`. Reading from the file will be covered in later stages. + 2. If your repository was created before 5th Oct 2023, it's possible that your `./spawn_redis_server.sh` script is not passing arguments to your program. To fix this, you'll need to edit `./spawn_redis_server.sh`. Check the [update CLI args PR](https://github.com/codecrafters-io/build-your-own-redis/pull/89/files) for details on how to do this. marketing_md: | In this stage, you'll add support for reading the config values related to where RDB files are stored. You'll implement the `CONFIG GET` command. @@ -493,13 +548,13 @@ stages: ./spawn_redis_server.sh --dir --dbfilename ``` - It'll then send a `keys *` command to your server. + It'll then send a `KEYS *` command to your server. ```bash - $ redis-cli keys "*" + $ redis-cli KEYS "*" ``` - The response to `keys *` should be a RESP array with one element: the key. + The response to `KEYS *` should be a RESP array with one element: the key. For example, let's say the RDB file contains a key called `foo`. The expected response will be: @@ -533,13 +588,13 @@ stages: ./spawn_redis_server.sh --dir --dbfilename ``` - It'll then send a `get ` command to your server. + It'll then send a `GET ` command to your server. ```bash - $ redis-cli get "foo" + $ redis-cli GET "foo" ``` - The response to `get ` should be a RESP bulk string with the value of the key. + The response to `GET ` should be a RESP bulk string with the value of the key. For example, let's say the RDB file contains a key called `foo` with the value `bar`. The expected response will be `$3\r\nbar\r\n`. @@ -568,13 +623,13 @@ stages: $ ./spawn_redis_server.sh --dir --dbfilename ``` - It'll then send a `keys *` command to your server. + It'll then send a `KEYS *` command to your server. ```bash - $ redis-cli keys "*" + $ redis-cli KEYS "*" ``` - The response to `keys *` should be a RESP array with the keys as elements. + The response to `KEYS *` should be a RESP array with the keys as elements. For example, let's say the RDB file contains two keys: `foo` and `bar`. The expected response will be: @@ -601,14 +656,14 @@ stages: $ ./spawn_redis_server.sh --dir --dbfilename ``` - It'll then send multiple `get ` commands to your server. + It'll then send multiple `GET ` commands to your server. ```bash - $ redis-cli get "foo" - $ redis-cli get "bar" + $ redis-cli GET "foo" + $ redis-cli GET "bar" ``` - The response to each `get ` command should be a RESP bulk string with the value corresponding to the key. + The response to each `GET ` command should be a RESP bulk string with the value corresponding to the key. marketing_md: | In this stage, you'll add support for reading multiple string values from an RDB file. @@ -628,11 +683,11 @@ stages: $ ./spawn_redis_server.sh --dir --dbfilename ``` - It'll then send multiple `get ` commands to your server. + It'll then send multiple `GET ` commands to your server. ```bash - $ redis-cli get "foo" - $ redis-cli get "bar" + $ redis-cli GET "foo" + $ redis-cli GET "bar" ``` When a key has expired, the expected response is `$-1\r\n` (a "null bulk string"). @@ -692,7 +747,7 @@ stages: When you run the `INFO` command against a Redis server, you'll see something like this: ``` - $ redis-cli info replication + $ redis-cli INFO replication # Replication role:master connected_slaves:0 @@ -758,7 +813,7 @@ stages: Here's an example usage of the `--replicaof` flag: ``` - ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 + ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" ``` In this example, we're starting a Redis server in replica mode. The server itself will listen for connections on port 6380, but it'll @@ -772,7 +827,7 @@ stages: The tester will execute your program like this: ``` - ./spawn_redis_server.sh --port --replicaof + ./spawn_redis_server.sh --port --replicaof " " ``` It'll then send the `INFO` command with `replication` as an argument to your server. @@ -828,7 +883,7 @@ stages: It'll then send the `INFO` command with `replication` as an argument to your server. ```bash - $ redis-cli info replication + $ redis-cli INFO replication ``` Your program should respond with a [Bulk string](https://redis.io/docs/reference/protocol-spec/#bulk-strings) where each line @@ -867,14 +922,14 @@ stages: The tester will execute your program like this: ``` - ./spawn_redis_server.sh --port --replicaof + ./spawn_redis_server.sh --port --replicaof " " ``` It'll then assert that the replica connects to the master and sends the `PING` command. ### Notes - - The `PING` command should be sent as a RESP Array, like this : `*1\r\n$4\r\nping\r\n` + - The `PING` command should be sent as a RESP Array, like this : `*1\r\n$4\r\nPING\r\n` marketing_md: | In this stage, you'll add support for starting the handshake from the Replica side. @@ -920,7 +975,7 @@ stages: The tester will execute your program like this: ``` - ./spawn_redis_server.sh --port --replicaof + ./spawn_redis_server.sh --port --replicaof " " ``` It'll then assert that the replica connects to the master and: @@ -980,7 +1035,7 @@ stages: The tester will execute your program like this: ``` - ./spawn_redis_server.sh --port --replicaof + ./spawn_redis_server.sh --port --replicaof " " ``` It'll then assert that the replica connects to the master and: @@ -1160,17 +1215,31 @@ stages: ### Command propagation - A master takes all write commands sent to it and propagates them to all connected replicas. The replicas - process these commands and apply them to their own state. + After the replication handshake is complete and the master has sent the RDB file to the replica, the + master starts propagating commands to the replica. + + When a master receives a "write" command from a client, it propagates the command to the replica. The + replica processes the command and updates its state. More on how this propagation works in the + "Replication connection" section below. + + Commands like `PING`, `ECHO` etc. are not considered "write" commands, so they aren't propagated. Commands like + `SET`, `DEL` etc. are considered "write" commands, so they are propagated. + + ### Replication connection - This propagation starts after the handshake is complete and the master has sent the RDB file to the replica. + Command propagation happens over the replication connection. This is the same connection that was used for the handshake. - Every "write" command is sent to the replica as a RESP array, and the replica processes it as if it were a command sent by a client. Unlike - regular commands, the replica doesn't send a response to these commands. The master keeps propagating commands as they come in without stopping - to read responses from the replica. + Propagated commands are sent as RESP arrays. For example, if the master receives `SET foo bar` as a command from a client, + it'll send `*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n` to all connected replicas over their respective replication connections. - Commands like `PING`, `ECHO` etc. are not considered "write" commands, so they aren't propagated. Commands like `SET`, `DEL` etc. are - considered "write" commands, so they are propagated. + Replicas process commands received over the replication connection just like they would process commands received from a client, + but with one difference: Replicas don't send responses back to the master. They just process the command silently and update their + state. + + Similarly, the master doesn't wait for a response from the replica when propagating commands. It just keeps sending commands as they + come in. + + There is one exception to this "no response" rule, the `REPLCONF GETACK` command. We'll learn about this in later stages. ### Tests @@ -1197,7 +1266,8 @@ stages: $ redis-cli SET baz 3 ``` - The tester will then assert that these commands were propagated to the replica server, in order. + It'll then assert that these commands were propagated to the replica, in order. The tester will + expect to receive these commands (encoded as RESP arrays) on the replication connection (the one used for the handshake). ### Notes @@ -1255,15 +1325,15 @@ stages: will work exactly like a regular command sent by a client, except that the replica doesn't send a response back to the master. - For example, if the command `set foo 1` is propagated to the replica by a master, the replica must update + For example, if the command `SET foo 1` is propagated to the replica by a master, the replica must update its database to set the value of `foo` to `1`. Unlike commands from a regular client though, it must not reply with `+OK\r\n`. ### Tests - THe tester will spawn a Redis master, and it'll then execute your program like this: + The tester will spawn a Redis master, and it'll then execute your program as a replica like this: ``` - ./spawn_redis_server.sh --port --replicaof + ./spawn_redis_server.sh --port --replicaof " " ``` Just like in the previous stages, your replica should complete the handshake with the master and receive an empty RDB file. @@ -1271,18 +1341,23 @@ stages: Once the RDB file is received, the master will propagate a series of write commands to your program. ```bash - set foo 1 # propagated from master to replica - set bar 2 # propagated from master to replica - set baz 3 # propagated from master to replica + SET foo 1 # propagated from master to replica + SET bar 2 # propagated from master to replica + SET baz 3 # propagated from master to replica ``` - The tester will then issue `get` commands to your program to check if the commands were processed correctly. + The tester will then issue `GET` commands to your program to check if the commands were processed correctly. ```bash $ redis-cli GET foo # expecting `1` back $ redis-cli GET bar # expecting `2` back # ... and so on ``` + + ### Notes + + - The propagated commands are sent as RESP arrays. So the command `SET foo 1` will be sent as `*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$1\r\n1\r\n`. + - It is **not** guaranteed that propagated commands will be sent one at a time. One "TCP segment" might contain bytes for multiple commands. marketing_md: | In this stage, you'll add support for processing commands received by the replica from the master. @@ -1295,40 +1370,48 @@ stages: ### ACKs - Unlike regular commands, when a master forwards commands to a replica via the replication connection, the replica doesn't - respond to each command. It just silently processes the commands and updates its state. +
+ Click to expand/collapse + + Unlike regular commands, when a master forwards commands to a replica via the replication connection, the replica doesn't + respond to each command. It just silently processes the commands and updates its state. - Since the master doesn't receive a response for each command, it needs another way to keep track of whether a replica is "in sync". - That's what ACKs are for. + Since the master doesn't receive a response for each command, it needs another way to keep track of whether a replica is "in sync". + That's what ACKs are for. - ACK is short for "acknowledgement". Redis masters periodically ask replicas to send ACKs. + ACK is short for "acknowledgement". Redis masters periodically ask replicas to send ACKs. - Each ACK contains an "offset", which is the number of bytes of commands processed by the replica. + Each ACK contains an "offset", which is the number of bytes of commands processed by the replica. - We'll learn about how this offset is calculated and used in later stages. In this stage, we'll focus on implementing the - mechanism through which a master asks for an ACK from a replica: the `REPLCONF GETACK` command. + We'll learn about how this offset is calculated and used in later stages. In this stage, we'll focus on implementing the + mechanism through which a master asks for an ACK from a replica: the `REPLCONF GETACK` command. +
### The `REPLCONF GETACK` command - When a master requires an ACK from a replica, it sends a `REPLCONF GETACK *` command to the replica. This is sent over - the replication connection (i.e. the connection that remains after the replication handshake is complete). +
+ Click to expand/collapse - When the replica receives this command, it responds with a `REPLCONF ACK ` response. The offset is the - number of bytes of commands processed by the replica. It starts at 0 and is incremented for every command processed by the replica. + When a master requires an ACK from a replica, it sends a `REPLCONF GETACK *` command to the replica. This is sent over + the replication connection (i.e. the connection that remains after the replication handshake is complete). - In this stage, you'll implement support for receiving the `REPLCONF GETACK *` command and responding with `REPLCONF ACK 0`. + When the replica receives this command, it responds with a `REPLCONF ACK ` response. The offset is the + number of bytes of commands processed by the replica. It starts at 0 and is incremented for every command processed by the replica. - You can hardcode the offset to 0 for now. We'll implement proper offset tracking in the next stage. + In this stage, you'll implement support for receiving the `REPLCONF GETACK *` command and responding with `REPLCONF ACK 0`. - The exact command received by the replica will look something like this: `*3\r\n$8\r\nreplconf\r\n$6\r\ngetack\r\n$1\r\n*\r\n` (that's - `["replconf", "getack", "*"]` encoded as a [RESP Array](https://redis.io/docs/reference/protocol-spec/#arrays)). + You can hardcode the offset to 0 for now. We'll implement proper offset tracking in the next stage. + + The exact command received by the replica will look something like this: `*3\r\n$8\r\nreplconf\r\n$6\r\ngetack\r\n$1\r\n*\r\n` (that's + `["replconf", "getack", "*"]` encoded as a [RESP Array](https://redis.io/docs/reference/protocol-spec/#arrays)). +
### Tests The tester will execute your program like this: ``` - ./spawn_redis_server.sh --port --replicaof + ./spawn_redis_server.sh --port --replicaof " " ``` Just like in the previous stages, your replica should complete the handshake with the master and receive an empty RDB file. @@ -1350,24 +1433,48 @@ stages: name: "ACKs with commands" difficulty: medium description_md: | - - - **🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below. + In this stage, you'll extend your `REPLCONF GETACK` implementation to respond with the number of bytes of commands processed by the replica. + + ### Offset tracking + +
+ Click to expand/collapse + 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. + + 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 `. The returned `` should only include the number of bytes of commands processed **before** receiving the `REPLCONF GETACK` command. + + As an example: + + - Let's say a replica connects to a master and completes the handshake. + - The master then sends a `REPLCONF GETACK *` command. + - The replica should respond with `REPLCONF ACK 0`. + - The returned offset is 0 since no commands have been processed yet (before receiving the `REPLCONF GETACK` command) + - The master then sends `REPLCONF GETACK *` again. + - The replica should respond with `REPLCONF ACK 37`. + - The returned offset is 37 since the first `REPLCONF GETACK` command was processed, and it was 37 bytes long. + - 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) + - The master then sends a `PING` command to the replica (masters do this periodically to notify replicas that the master is still alive). + - The replica must silently process the `PING` command and update its offset. It should not send a response back to the master. + - The master then sends `REPLCONF GETACK *` again (this is the third REPLCONF GETACK command received by the replica) + - The replica should respond with `REPLCONF ACK 88`. + - The returned offset is 88 (37 + 37 + 14) + - 37 for the first `REPLCONF GETACK` command + - 37 for the second `REPLCONF GETACK` command + - 14 for the `PING` command + - Note that the third `REPLCONF GETACK` command is not included in the offset, since the value should + only include the number of bytes of commands processed **before** receiving the current `REPLCONF GETACK` command. + - ... and so on + +
### Tests The tester will execute your program like this: ``` - ./spawn_redis_server.sh --port --replicaof + ./spawn_redis_server.sh --port --replicaof " " ``` Just like in the previous stages, your replica should complete the handshake with the master and receive an empty RDB file. @@ -1375,21 +1482,24 @@ stages: The master will then propagate a series of commands to your replica. These commands will be interleaved with `REPLCONF GETACK *` commands. ```bash - replconf getack * # expecting REPLCONF ACK 0, since 0 bytes have been processed - replconf getack * # expecting REPLCONF ACK 37 (0 + 37 for the replconf command) + REPLCONF getack * # expecting REPLCONF ACK 0, since 0 bytes have been processed - ping # master checking whether replica is alive - replconf getack * # expecting REPLCONF ACK 88 (37 + 37 for the replconf command + 14 for the ping command) + ping # master sending a ping command to notify the replica that it's still alive + REPLCONF getack * # expecting REPLCONF ACK 51 (37 for the first REPLCONF command + 14 for the ping command) set foo 1 # propagated from master to replica - replconf getack * # expecting REPLCONF ACK 154 (88 + 37 for the replconf command + 29 for the set command) + set bar 2 # propagated from master to replica + REPLCONF getack * # expecting REPLCONF ACK 109 (51 + 29 for the first set command + 29 for the second set command) ``` ### Notes - - 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 check if they're alive. - - Replicas should update their offset to account for **all** commands propagated from the master, including `ping` and `replconf` itself. + - The offset should only include the number of bytes of commands processed **before** receiving the current `REPLCONF GETACK` command. + - 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. + - Replicas should update their offset to account for **all** commands propagated from the master, including `PING` and `REPLCONF` itself. + - The response should be encoded as a [RESP Array](https://redis.io/docs/reference/protocol-spec/#arrays), like + this: `*3\r\n$8\r\nREPLCONF\r\n$3\r\nACK\r\n$3\r\n154\r\n`. marketing_md: | In this stage, you'll add support for returning an ACK back to master as a response to GETACK. @@ -1415,17 +1525,17 @@ stages: ./spawn_redis_server.sh ``` - A redis client will then connect to your master and send `wait 0 60000`: + A redis client will then connect to your master and send `WAIT 0 60000`: ```bash - $ redis-cli wait 0 60000 + $ redis-cli WAIT 0 60000 ``` It'll expect to receive `0` back immediately, since no replicas are connected. ### Notes - - You can hardcode `0` as the response for the wait command in this stage. We'll get to tracking the number of replicas and responding + - You can hardcode `0` as the response for the WAIT command in this stage. We'll get to tracking the number of replicas and responding accordingly in the next stages. marketing_md: | In this stage, you'll start implementing the WAIT command on your master. @@ -1494,21 +1604,21 @@ stages: It'll then start **multiple** replicas that connect to your server. Each will complete the handshake and expect to receive an empty RDB file. The tester will then connect to your master as a Redis client (not one of the replicas) and send multiple write commands interleaved - with `wait` commands: + with `WAIT` commands: ```bash - $ redis-cli set foo 123 - $ redis-cli wait 1 500 # (must wait until either 1 replica has processed previous commands or 500ms have passed) + $ redis-cli SET foo 123 + $ redis-cli WAIT 1 500 # (must wait until either 1 replica has processed previous commands or 500ms have passed) - $ redis-cli set bar 456 - $ redis-cli wait 2 500 # (must wait until either 2 replicas have processed previous commands or 500ms have passed) + $ redis-cli SET bar 456 + $ redis-cli WAIT 2 500 # (must wait until either 2 replicas have processed previous commands or 500ms have passed) ``` ### Notes - - The `wait` command should return when either (a) the specified number of replicas have acknowledged the command, or (b) the timeout expires. - - The `wait` command should always return the number of replicas that have acknowledged the command, even if the timeout expires. - - The returned number of replicas might be lesser than or greater than the expected number of replicas specified in the `wait` command. + - The `WAIT` command should return when either (a) the specified number of replicas have acknowledged the command, or (b) the timeout expires. + - The `WAIT` command should always return the number of replicas that have acknowledged the command, even if the timeout expires. + - The returned number of replicas might be lesser than or greater than the expected number of replicas specified in the `WAIT` command. marketing_md: | In this stage, you'll finish implementing the WAIT command on your master. @@ -1522,28 +1632,30 @@ stages: ### The TYPE command - [TYPE](https://redis.io/commands/type/) is the command used in order to get the type of a value stored at a given key. The different types that can be returned are: string, list, set, zset, hash, and stream. + The [TYPE](https://redis.io/commands/type/) command returns the type of value stored at a given key. + + It returns one of the following types: string, list, set, zset, hash, and stream. Here's how it works: ```bash - $ redis-cli set some_key foo + $ redis-cli SET some_key foo "OK" - $ redis-cli type some_key + $ redis-cli TYPE some_key "string" ``` If a key doesn't exist, the return value will be "none". ```bash - $ redis-cli type missing_key + $ redis-cli TYPE missing_key "none" ``` - The return value of the type command is encoded as a [simple string](https://redis.io/docs/reference/protocol-spec/#simple-strings). + The return value is encoded as a [simple string](https://redis.io/docs/reference/protocol-spec/#simple-strings). ### Tests - + The tester will execute your program like this: ```bash @@ -1553,29 +1665,35 @@ stages: It'll then send a `SET` command to your server. ```bash - $ redis-cli set some_key foo + $ redis-cli SET some_key foo ``` It'll then send a `TYPE` command to your server. ```bash - $ redis-cli type some_key + $ redis-cli TYPE some_key ``` - Your server should respond with `+string\r\n`, which is `string` encoded as a RESP simple string. It'll then send another `TYPE` command with a missing key. + Your server should respond with `+string\r\n`, which is `string` encoded as a [RESP simple string](https://redis.io/docs/reference/protocol-spec/#simple-strings). + + It'll then send another `TYPE` command with a missing key. ```bash - $ redis-cli type missing_key + $ redis-cli TYPE missing_key ``` - Your server should respond with `+none\r\n`, which is `none` encoded as a RESP simple string. + Your server should respond with `+none\r\n`, which is `none` encoded as a [RESP simple string](https://redis.io/docs/reference/protocol-spec/#simple-strings). + + ### Notes + + - For now, you only need to handle the "string" and "none" types. We'll add support for the "stream" type in the next stage. marketing_md: | In this stage, you'll add support for the `TYPE` command. - slug: "streams-xadd" primary_extension_slug: "streams" name: "Create a stream" - difficulty: easy + difficulty: medium description_md: | In this stage, you'll add support for creating a [Redis stream](https://redis.io/docs/data-types/streams/) using the `XADD` command. @@ -1588,35 +1706,37 @@ stages: For example, if you were using a Redis stream to store real-time data from a temperature & humidity monitor, the contents of the stream might look like this: ```yaml - - 1526985054069-0 # (ID of the first entry) - temperature: 36 # (A key value pair in the first entry) - humidity: 95 # (Another key value pair in the first entry) + entries: + - id: 1526985054069-0 # (ID of the first entry) + temperature: 36 # (A key value pair in the first entry) + humidity: 95 # (Another key value pair in the first entry) - - 1526985054079-0 # (ID of the second entry) - temperature: 37 # (A key value pair in the first entry) - humidity: 94 # (Another key value pair in the first entry) + - id: 1526985054079-0 # (ID of the second entry) + temperature: 37 # (A key value pair in the first entry) + humidity: 94 # (Another key value pair in the first entry) - # ... (and so on) + # ... (and so on) ``` - The entry IDs will be looked at more closely in the upcoming stages. + We'll take a closer look at the format of entry IDs (`1526985054069-0` and `1526985054079-0` in the example above) in the upcoming stages. ### The XADD command - [XADD](https://redis.io/commands/xadd/) is the command used to append an entry to the stream. If a stream doesn't exist already, it is created. + The [XADD](https://redis.io/commands/xadd/) command appends an entry to a stream. If a stream doesn't exist already, it is created. Here's how it works: ```bash - $ redis-cli xadd some_key 1526919030474-0 temperature 36 humidity 95 - "1526919030474-0" + $ redis-cli XADD stream_key 1526919030474-0 temperature 36 humidity 95 + "1526919030474-0" # (ID of the entry created) ``` The return value is the ID of the entry created, encoded as a [bulk string](https://redis.io/docs/reference/protocol-spec/#bulk-strings). `XADD` supports other optional arguments, but we won't deal with them in this challenge. - In this stage, we'll focus on adding support for explicit IDs and at least one key value pair. + `XADD` also supports auto-generating entry IDs. We'll add support for that in later stages. For now, we'll only deal with + explicit IDs (like `1526919030474-0` in the example above). ### Tests @@ -1629,19 +1749,24 @@ stages: It'll then send an `XADD` command to your server and expect the ID as a response. ```bash - $ redis-cli xadd stream_key 0-1 foo bar + $ redis-cli XADD stream_key 0-1 foo bar + "0-1" ``` - Your server should respond with `$3\r\n0-1\r\n`, which is `0-1` encoded as a RESP bulk string. The tester will then send a `TYPE` command to your server. + Your server should respond with `$3\r\n0-1\r\n`, which is `0-1` encoded as a [RESP bulk string](https://redis.io/docs/reference/protocol-spec/#bulk-strings). + + The tester will then send a `TYPE` command to your server. ```bash - $ redis-cli type stream_key + $ redis-cli TYPE stream_key + "stream" ``` - Your server should respond with `+stream\r\n`, which is `stream` encoded as a RESP simple string. + Your server should respond with `+stream\r\n`, which is `stream` encoded as a [RESP simple string](https://redis.io/docs/reference/protocol-spec/#simple-strings). ### Notes - - You can ignore the ability to parse multiple key value pairs. + + - You still need to handle the "string" and "none" return values for the `TYPE` command. "stream" should only be returned for keys that are streams. marketing_md: | In this stage, you'll add support for creating a [Redis stream](https://redis.io/docs/data-types/streams/) using the `XADD` command. @@ -1650,60 +1775,71 @@ stages: name: "Validating entry IDs" difficulty: easy description_md: | - In this stage, you'll enhance the `XADD` command by extending support for explicit IDs. + In this stage, you'll add support for validating entry IDs to the `XADD` command. ### Entry IDs - - Here's an example of stream entries in the previous stage: + + Here's an example of stream entries from the previous stage: ```yaml - - 1526985054069-0 # (ID of the first entry) - temperature: 36 # (A key value pair in the first entry) - humidity: 95 # (Another key value pair in the first entry) + entries: + - id: 1526985054069-0 # (ID of the first entry) + temperature: 36 # (A key value pair in the first entry) + humidity: 95 # (Another key value pair in the first entry) - - 1526985054079-0 # (ID of the second entry) - temperature: 37 # (A key value pair in the first entry) - humidity: 94 # (Another key value pair in the first entry) + - id: 1526985054079-0 # (ID of the second entry) + temperature: 37 # (A key value pair in the first entry) + humidity: 94 # (Another key value pair in the first entry) - # ... (and so on) + # ... (and so on) ``` - Entry IDs are always composed of two integers: `-`. + Entry IDs are always composed of two integers: `-`. + + Entry IDs are unique within a stream, and they're guaranteed to be incremental - i.e. an + entry added later will always have an ID greater than an entry added in the past. More + on this in the next section. + + ### Specifying entry IDs in XADD There are multiple formats in which the ID can be specified in the XADD command: + - Explicit ("1526919030474-0") (**This stage**) - Auto-generate only sequence number ("1526919030474-*") (Next stages) - Auto-generate time part and sequence number ("*") (Next stages) - IDs are guaranteed to be incremental within a stream - i.e. an entry added later will always have an ID greater than an entry added in the past. + In this stage, we'll only deal with explicit IDs. We'll add support for the other two cases in the next stages. - `millisecondsTime` should be equal to or greater than the `millisecondsTime` of the last entry. If they're equal, the `sequenceNumber` should be greater than the `sequenceNumber` of the last entry. + Your XADD implementation should validate the ID passed in. - Otherwise, the response would be an error. + - The ID should be greater than the ID of the last entry in the stream. + - The `millisecondsTime` part of the ID should be greater than or equal to the `millisecondsTime` of the last entry. + - If the `millisecondsTime` part of the ID is equal to the `millisecondsTime` of the last entry, the `sequenceNumber` part of the ID should be greater than the `sequenceNumber` of the last entry. + - If the stream is empty, the ID should be greater than `0-0` - Here's an example of that: + Here's an example of adding an entry with a valid ID followed by an invalid ID: ```bash - $ redis-cli xadd some_key 1-1 foo bar + $ redis-cli XADD some_key 1-1 foo bar "1-1" - $ redis-cli xadd some_key 1-1 bar baz - "(error) ERR The ID specified in XADD is equal or smaller than the target stream top item" + $ redis-cli XADD some_key 1-1 bar baz + (error) ERR The ID specified in XADD is equal or smaller than the target stream top item ``` - Here's another example: + Here's another such example: ```bash - $ redis-cli xadd some_key 1-1 foo bar + $ redis-cli XADD some_key 1-1 foo bar "1-1" - $ redis-cli xadd some_key 0-2 bar baz - "(error) ERR The ID specified in XADD is equal or smaller than the target stream top item" + $ redis-cli XADD some_key 0-2 bar baz + (error) ERR The ID specified in XADD is equal or smaller than the target stream top item ``` - The minimum explicit id that Redis supports is 0-1. Passing in an ID lower than that would result to an error. + The minimum entry ID that Redis supports is 0-1. Passing in an ID lower than should result in an error. ```bash - $ redis-cli xadd some_key 0-0 bar baz - "(error) ERR The ID specified in XADD must be greater than 0-0" + $ redis-cli XADD some_key 0-0 bar baz + (error) ERR The ID specified in XADD must be greater than 0-0 ``` ### Tests @@ -1717,51 +1853,73 @@ stages: It'll create a few entries usind `XADD`. ```bash - $ redis-cli xadd stream_key 1-1 foo bar - $ redis-cli xadd stream_key 1-2 bar baz + $ redis-cli XADD stream_key 1-1 foo bar + "1-1" + $ redis-cli XADD stream_key 1-2 bar baz + "1-2" ``` It'll send another `XADD` command with the same time and sequence number as the last entry. ```bash - $ redis-cli xadd stream_key 1-2 baz foo + $ redis-cli XADD stream_key 1-2 baz foo + (error) ERR The ID specified in XADD is equal or smaller than the target stream top item ``` - Your server should respond with `-ERR The ID specified in XADD is equal or smaller than the target stream top item\r\n`, which is the error message in the example encoded as a [simple error](https://redis.io/docs/reference/protocol-spec/#simple-errors). It'll then send another `XADD` command with a smaller value for the time and a larger value for the sequence number. + Your server should respond with "-ERR The ID specified in XADD is equal or smaller than the target stream top item\r\n", which is the error message above encoded as a + [simple error](https://redis.io/docs/reference/protocol-spec/#simple-errors). + + The tester will then send another `XADD` command with a smaller value for the time and a larger value for the sequence number. ```bash - $ redis-cli xadd stream_key 0-3 baz foo + $ redis-cli XADD stream_key 0-3 baz foo + (error) ERR The ID specified in XADD is equal or smaller than the target stream top item ``` - Your server should also respond with the same error message encoded as a RESP simple error. It'll then send another `XADD` command with `0-0` as the ID. + Your server should also respond with the same error message. + + After that, the tester will send another `XADD` command with `0-0` as the ID. ```bash - $ redis-cli xadd stream_key 0-0 baz foo + $ redis-cli XADD stream_key 0-0 baz foo ``` - Your server should respond with `-ERR The ID specified in XADD must be greater than 0-0\r\n`, which is the error message in the example also encoded as a RESP simple error. + Your server should respond with "-ERR The ID specified in XADD must be greater than 0-0\r\n", which is the error message above encoded as a + [RESP simple error](https://redis.io/docs/reference/protocol-spec/#simple-errors). marketing_md: | In this stage, you'll enhance the `XADD` command by extending support for explicit IDs. - slug: "streams-xadd-partial-autoid" primary_extension_slug: "streams" name: "Partially auto-generated IDs" - difficulty: easy + difficulty: medium description_md: | - In this stage, you'll enhance the `XADD` command by adding the option to use `*` as the sequence number. + In this stage, you'll extend your `XADD` command implementation to support auto-generating the + sequence number part of the entry ID. ### Specifying entry IDs in XADD As a recap, there are multiple formats in which the ID can be specified in the `XADD` command: + - Explicit ("1526919030473-0") (Previous stage) - Auto-generate only sequence number ("1526919030474-*") (**This stage**) - Auto-generate time part and sequence number ("*") (Next stage) - We dealt with explicit IDs in the last stage. Now, we'll handle the second case. + We dealt with explicit IDs in the last stage. We'll handle the second case in this stage. - When `*` is used for the sequence number with the `XADD` command, Redis auto-generates a unique incrementing ID for the entry being appended to the stream. + When `*` is used for the sequence number, Redis picks the last sequence number used in the + stream (for the same time part) and increments it by 1. - The default sequence number is 0. The only exception is when the time is also 0. In that case, the default sequence number is 1. + The default sequence number is 0. The only exception is when the time part is also 0. In that case, the default sequence number is 1. + + Here's an example of adding an entry with `*` as the sequence number: + + ```bash + $ redis-cli XADD some_key "1-*" foo bar + "1-0" # If there are no entries, the sequence number will be 0 + $ redis-cli XADD some_key "1-*" bar baz + "1-1" # Adding another entry will increment the sequence number + ``` ### Tests @@ -1774,44 +1932,55 @@ stages: It'll send an `XADD` command with `*` as the sequence number. ```bash - $ redis-cli xadd stream_key 0-* foo bar + $ redis-cli XADD stream_key 0-* foo bar ``` - Your server should respond with `$3\r\n0-1\r\n`, which is `0-1` encoded as a RESP bulk string. It'll then send another `XADD` command with `*` as the sequence number, but this time with 1 as the time. + Your server should respond with `$3\r\n0-1\r\n`, which is `0-1` encoded as a RESP bulk string. + + It'll then send another `XADD` command with `*` as the sequence number, but this time with a + random number as the time part. ```bash - $ redis-cli xadd stream_key 1-* foo bar + $ redis-cli XADD stream_key 5-* foo bar ``` - Your server should respond with `$3\r\n1-0\r\n`, which is `1-0` encoded as a RESP bulk string. It'll send the same command again. + Your server should respond with `$3\r\n5-0\r\n`, which is `5-0` encoded as a [RESP bulk string](https://redis.io/docs/reference/protocol-spec/#bulk-strings) + + It'll send the same command again. ```bash - $ redis-cli xadd stream_key 1-* bar baz + $ redis-cli XADD stream_key 5-* bar baz ``` - Your server should respond with `$3\r\n1-1\r\n`, which is `1-1` encoded as a RESP bulk string. + Your server should respond with `$3\r\n5-1\r\n`, which is `5-1` encoded as a [RESP bulk string](https://redis.io/docs/reference/protocol-spec/#bulk-strings) + + ### Notes + + - The tester will use a random number for the time part (we use `5` in the example above). marketing_md: | In this stage, you'll enhance the `XADD` command by adding the option to use `*` as the sequence number. - slug: "streams-xadd-full-autoid" primary_extension_slug: "streams" - name: "Full auto-generated IDs" - difficulty: easy + name: "Fully auto-generated IDs" + difficulty: medium description_md: | - In this stage, you'll enhance the `XADD` command by adding the option to use `*` as the entry ID. + In this stage, you'll extend your `XADD` command implementation to support auto-generating entry IDs. - ### Specifying entry IDs in XADD (Continued) + ### Specifying entry IDs in XADD (Continued...) As a recap, there are multiple formats in which the ID can be specified in the `XADD` command: + - Explicit ("1526919030474-0") (Previous stages) - Auto-generate only sequence number ("1526919030473-*") (Previous stages) - Auto-generate time part and sequence number ("*") (**This stage**) We'll now handle the third case. - When `*` is used with the `XADD` command, Redis takes care of generating a unique incrementing ID for the message being appended to the stream. + When `*` is used with the `XADD` command, Redis auto-generates a unique auto-incrementing ID for the message being appended to the stream. - Redis defaults to using the current unix time in milliseconds and 0 for the sequence number. If the time already exists in the stream, the sequence number for that record incremented by one will be used. + Redis defaults to using the current unix time in milliseconds for the time part and 0 for the sequence number. If the + time already exists in the stream, the sequence number for that record incremented by one will be used. ### Tests @@ -1821,13 +1990,19 @@ stages: $ ./spawn_redis_server.sh ``` - It'll create an entry with `*` as the ID. + It'll then create an entry with `*` as the ID. ```bash - $ redis-cli xadd stream_key * foo bar + $ redis-cli XADD stream_key * foo bar ``` - Your server should respond with `$13\r\n-0\r\n`, which is `-0` encoded as a RESP bulk string. + Your server should respond with a string like `$15\r\n1526919030474-0\r\n`, which is `1526919030474-0` encoded as a RESP bulk string. + + ### Notes + + - The time part of the ID should be the current unix time in **milliseconds**, not seconds. + - The tester doesn't test the case where a time part already exists in the stream and the sequence + number is incremented. This is difficult to test reliably since we'd need to send 2 commands within the same millisecond. marketing_md: | In this stage, you'll enhance the `XADD` command by adding the option to use `*` as the entry ID. @@ -1840,31 +2015,20 @@ stages: ### The XRANGE command - [XRANGE](https://redis.io/commands/xrange/) is the command is used for retrieving a range of entries from a stream within defined start and end IDs. + The [XRANGE](https://redis.io/commands/xrange/) command retrieves a range of entries from a stream. - Here's how it works: - We'll use our previous example for entries existing in a stream. - - ```yaml - - 1526985054069-0 # (ID of the first entry) - temperature: 36 # (A key value pair in the first entry) - humidity: 95 # (Another key value pair in the first entry) + It takes two arguments: `start` and `end`. Both are entry IDs. The command returns all entries in the + stream with IDs between the `start` and `end` IDs. This range is "inclusive", which means that the response + will includes entries with IDs that are equal to the `start` and `end` IDs. - - 1526985054079-0 # (ID of the second entry) - temperature: 37 # (A key value pair in the first entry) - humidity: 94 # (Another key value pair in the first entry) - - # ... (and so on) - ``` - - This is what the command looks like: + Here's an example of how it works: ```bash - $ redis-cli xadd some_key 1526985054069-0 temperature 36 humidity 95 - "1526985054069-0" - $ redis-cli xadd some_key 1526985054079-0 temperature 37 humidity 94 + $ redis-cli XADD some_key 1526985054069-0 temperature 36 humidity 95 + "1526985054069-0" # (ID of the first added entry) + $ redis-cli XADD some_key 1526985054079-0 temperature 37 humidity 94 "1526985054079-0" - $ redis-cli xrange some_key 1526985054069 1526985054079 + $ redis-cli XRANGE some_key 1526985054069 1526985054079 1) 1) 1526985054069-0 2) 1) temperature 2) 36 @@ -1877,11 +2041,17 @@ stages: 4) 94 ``` - The sequence number doesn't need to be included in the start and end IDs provided to the command. If not provided, the it defaults to a sequence number of 0 for the start and the maximum sequence number for the end. + The sequence number doesn't need to be included in the start and end IDs provided to the command. If not provided, + XRANGE defaults to a sequence number of 0 for the start and the maximum sequence number for the end. - The start and end IDs are inclusive, which means that the response includes entries with IDs matching both the start and end. The only way to get a single value from a stream is through the `XRANGE` command with the same value for the start and end IDs. + The return value of the command is not exactly what is shown in the example above. This is already formatted by redis-cli. - The return value of the command is not exactly what is shown in the example above. This is already formatted by the CLI. What is instead returned is actually a [list](https://redis.io/docs/reference/protocol-spec/#arrays) of an array of two items. The items being the ID and a list of key value pairs. + The actual return value is a [RESP Array](https://redis.io/docs/reference/protocol-spec/#arrays) of arrays. + + - Each inner array represents an entry. + - The first item in the inner array is the ID of the entry. + - The second item is a list of key value pairs, where the key value pairs are represented as a list of strings. + - The key value pairs are in the order they were added to the entry. The return value of the example above is actually something like this: @@ -1919,6 +2089,7 @@ stages: $2\r\n36\r\n $8\r\nhumidity\r\n $2\r\n95\r\n + *2\r\n $15\r\n1526985054079-0\r\n *4\r\n $11\r\ntemperature\r\n @@ -1927,7 +2098,8 @@ stages: $2\r\n94\r\n ``` - The lines are separated into new lines for readability. The return value is just one value. + In the code block above, the response is separated into multiple lines for readability. The actual + return value doesn't contain any additional newlines. ### Tests @@ -1940,37 +2112,40 @@ stages: First, it'll add a few entries. ```bash - $ redis-cli xadd stream_key 0-1 foo bar - $ redis-cli xadd stream_key 0-2 bar baz - $ redis-cli xadd stream_key 0-3 baz foo + $ redis-cli XADD stream_key 0-1 foo bar + "0-1" + $ redis-cli XADD stream_key 0-2 bar baz + "0-2" + $ redis-cli XADD stream_key 0-3 baz foo + "0-3" ``` Then, it'll send an `XRANGE` command to your server. ```bash - $ redis-cli xrange stream_key 0-2 0-3 + $ redis-cli XRANGE stream_key 0-2 0-3 ``` - Your server should respond with the following: + Your server should respond with the following (encoded as a RESP Array): - ```text - *2\r\n - *2\r\n - $3\r\n0-2\r\n - *2\r\n - $3\r\nbar\r\n - $3\r\nbaz\r\n - *2\r\n - $3\r\n0-3\r\n - *2\r\n - $3\r\nbaz\r\n - $3\r\nfoo\r\n + ```json + [ + [ + "0-2", + [ + "bar", + "baz" + ] + ], + [ + "0-3", + [ + "baz", + "foo" + ] + ] + ] ``` - - This is the RESP encoded representation of `[["0-2", ["bar", "baz"]], ["0-3", ["baz", "foo"]]]`. - - ### Notes - - In the response, the items are separated onto new lines for readability. The tester expects all of these to be in one line. marketing_md: | In this stage, you'll add support for querying data from a stream using the `XRANGE` command. @@ -1982,32 +2157,19 @@ stages: In this stage, you'll extend support for `XRANGE` to allow querying using `-`. ### Using XRANGE with - - + In the previous stage, we saw that `XRANGE` takes `start` and `end` as arguments. In addition to accepting an explicit entry ID, `start` can also be specified as `-`. When `-` is used, `XRANGE` retrieves entries from the beginning of the stream. - Here's an example of how that works: - We'll use our previous example for entries existing in a stream. - - ```yaml - - 1526985054069-0 # (ID of the first entry) - temperature: 36 # (A key value pair in the first entry) - humidity: 95 # (Another key value pair in the first entry) - - - 1526985054079-0 # (ID of the second entry) - temperature: 37 # (A key value pair in the first entry) - humidity: 94 # (Another key value pair in the first entry) - - # ... (and so on) - ``` + Here's an example of how that works. ```bash - $ redis-cli xadd some_key 1526985054069-0 temperature 36 humidity 95 + $ redis-cli XADD some_key 1526985054069-0 temperature 36 humidity 95 "1526985054069-0" - $ redis-cli xadd some_key 1526985054079-0 temperature 37 humidity 94 + $ redis-cli XADD some_key 1526985054079-0 temperature 37 humidity 94 "1526985054079-0" - $ redis-cli xrange some_key - 1526985054079 + $ redis-cli XRANGE some_key - 1526985054079 1) 1) 1526985054069-0 2) 1) temperature 2) 36 @@ -2020,6 +2182,8 @@ stages: 4) 94 ``` + In the example above, `XRANGE` retrieves all entries from the beginning of the stream to the entry with ID `1526985054079-0`. + ### Tests The tester will execute your program like this: @@ -2031,37 +2195,46 @@ stages: It'll then create a few entries. ```bash - $ redis-cli xadd stream_key 0-1 foo bar - $ redis-cli xadd stream_key 0-2 bar baz - $ redis-cli xadd stream_key 0-3 baz foo + $ redis-cli XADD stream_key 0-1 foo bar + "0-1" + $ redis-cli XADD stream_key 0-2 bar baz + "0-2" + $ redis-cli XADD stream_key 0-3 baz foo + "0-3" ``` It'll then send an `XRANGE` command to your server. ```bash - $ redis-cli xrange stream_key - 0-2 + $ redis-cli XRANGE stream_key - 0-2 + 1) 1) 0-1 + 2) 1) foo + 2) bar + 2) 1) 0-2 + 2) 1) bar + 2) baz ``` - Your server should respond with the following: + Your server should respond with the following, encoded as a [RESP Array](https://redis.io/docs/reference/protocol-spec/#arrays): - ```text - *2\r\n - *2\r\n - $3\r\n0-1\r\n - *2\r\n - $3\r\nfoo\r\n - $3\r\nbar\r\n - *2\r\n - $3\r\n0-2\r\n - *2\r\n - $3\r\nbar\r\n - $3\r\nbaz\r\n + ```json + [ + [ + "0-1", + [ + "foo", + "bar" + ] + ], + [ + "0-2", + [ + "bar", + "baz" + ] + ] + ] ``` - - This is the RESP encoded representation of `[["0-1", ["foo", "bar"]], ["0-2", ["bar", "baz"]]]`. - - ### Notes - - In the response, the items are separated onto new lines for readability. The tester expects all of these to be in one line. marketing_md: | In this stage, you'll extend support for `XRANGE` to allow querying using `-`. @@ -2073,20 +2246,21 @@ stages: In this stage, you'll extend support for `XRANGE` to allow querying using `+`. ### Using XRANGE with + - + In the previous stage, we saw that `XRANGE` takes `start` and `end` as arguments. In addition to accepting an explicit entry ID, `end` can also be specified as `+`. When `+` is used, `XRANGE` retrieves entries until the end of the stream. - Here's an example of how that works: + Here's an example of how that works. + We'll use our previous example for entries existing in a stream. ```bash - $ redis-cli xadd some_key 1526985054069-0 temperature 36 humidity 95 + $ redis-cli XADD some_key 1526985054069-0 temperature 36 humidity 95 "1526985054069-0" - $ redis-cli xadd some_key 1526985054079-0 temperature 37 humidity 94 + $ redis-cli XADD some_key 1526985054079-0 temperature 37 humidity 94 "1526985054079-0" - $ redis-cli xrange some_key 1526985054069 + + $ redis-cli XRANGE some_key 1526985054069 + 1) 1) 1526985054069-0 2) 1) temperature 2) 36 @@ -2110,15 +2284,15 @@ stages: It'll then create a few entries. ```bash - $ redis-cli xadd stream_key 0-1 foo bar - $ redis-cli xadd stream_key 0-2 bar baz - $ redis-cli xadd stream_key 0-3 baz foo + $ redis-cli XADD stream_key 0-1 foo bar + $ redis-cli XADD stream_key 0-2 bar baz + $ redis-cli XADD stream_key 0-3 baz foo ``` It'll then send an `XRANGE` command to your server. ```bash - $ redis-cli xrange stream_key 0-2 + + $ redis-cli XRANGE stream_key 0-2 + ``` Your server should respond with the following: @@ -2137,7 +2311,26 @@ stages: $3\r\nfoo\r\n ``` - This is the RESP encoded representation of [["0-2", ["bar", "baz"]], ["0-3", ["baz", "foo"]]]. + This is the RESP encoded representation of the following. + + ```json + [ + [ + "0-2", + [ + "bar", + "baz" + ] + ], + [ + "0-3", + [ + "baz", + "foo" + ] + ] + ] + ``` ### Notes - In the response, the items are separated onto new lines for readability. The tester expects all of these to be in one line. @@ -2152,29 +2345,32 @@ stages: In this stage, you'll add support to querying a stream using the `XREAD` command. ### The XREAD command - + [XREAD](https://redis.io/commands/xread/) is used to read data from one or more streams, starting from a specified entry ID. - Here's how it works. Let's use the entries previously shown as an example: + Here's how it works. + + Let's use the entries previously shown as an example. ```yaml - - 1526985054069-0 # (ID of the first entry) - temperature: 36 # (A key value pair in the first entry) - humidity: 95 # (Another key value pair in the first entry) + entries: + - id: 1526985054069-0 # (ID of the first entry) + temperature: 36 # (A key value pair in the first entry) + humidity: 95 # (Another key value pair in the first entry) - - 1526985054079-0 # (ID of the second entry) - temperature: 37 # (A key value pair in the first entry) - humidity: 94 # (Another key value pair in the first entry) + - id: 1526985054079-0 # (ID of the second entry) + temperature: 37 # (A key value pair in the first entry) + humidity: 94 # (Another key value pair in the first entry) - # ... (and so on) + # ... (and so on) ``` ```bash - $ redis-cli xadd some_key 1526985054069-0 temperature 36 humidity 95 + $ redis-cli XADD some_key 1526985054069-0 temperature 36 humidity 95 "1526985054069-0" - $ redis-cli xadd some_key 1526985054079-0 temperature 37 humidity 94 + $ redis-cli XADD some_key 1526985054079-0 temperature 37 humidity 94 "1526985054079-0" - $ redis-cli xread streams some_key 1526985054069-0 + $ redis-cli XREAD streams some_key 1526985054069-0 1) 1) "some_key" 2) 1) 1) 1526985054079-0 2) 1) temperature @@ -2241,13 +2437,13 @@ stages: First, an entry will be added. ```bash - $ redis-cli xadd stream_key 0-1 temperature 96 + $ redis-cli XADD stream_key 0-1 temperature 96 ``` It'll then send an `XREAD` command to your server. ```bash - $ redis-cli xread streams stream_key 0-0 + $ redis-cli XREAD streams stream_key 0-0 ``` Your server should respond with the following: @@ -2264,7 +2460,24 @@ stages: $2\r\n96\r\n ``` - This is the RESP encoded representation of `["stream_key", [["0-1", ["temperature", "96"]]]]`. + This is the RESP encoded representation of the following. + + ```json + [ + [ + "stream_key", + [ + [ + "0-1", + [ + "temperature", + "96" + ] + ] + ] + ] + ] + ``` ### Notes - In the response, the items are separated onto new lines for readability. The tester expects all of these to be in one line. @@ -2289,14 +2502,14 @@ stages: First, an entry will be added to a couple of streams. ```bash - $ redis-cli xadd stream_key 0-1 temperature 95 - $ redis-cli xadd other_stream_key 0-2 humidity 97 + $ redis-cli XADD stream_key 0-1 temperature 95 + $ redis-cli XADD other_stream_key 0-2 humidity 97 ``` It'll then send an `XREAD` command to your server with multiple streams. ```bash - $ redis-cli xread streams stream_key other_stream_key 0-0 0-1 + $ redis-cli XREAD streams stream_key other_stream_key 0-0 0-1 ``` Your server should respond with the following: @@ -2321,7 +2534,36 @@ stages: $2\r\n97\r\n ``` - This is the RESP encoded representation of `[["stream_key", [["0-1", ["foo", "bar"]]]], ["other_stream_key", [["0-2", ["bar", "baz"]]]]]`. + This is the RESP encoded representation of the following. + + ```json + [ + [ + "stream_key", + [ + [ + "0-1", + [ + "foo", + "bar" + ] + ] + ] + ], + [ + "other_stream_key", + [ + [ + "0-2", + [ + "bar", + "baz" + ] + ] + ] + ] + ] + ``` ### Notes - In the response, the items are separated onto new lines for readability. The tester expects all of these to be in one line. @@ -2330,54 +2572,57 @@ stages: - slug: "streams-xread-block" primary_extension_slug: "streams" - name: "Support blocking reads" + name: "Blocking reads" difficulty: hard description_md: | - In this stage, you'll add extend support to `XREAD` to allow for turning it into a blocking command. + In this stage, you'll extend support to `XREAD` to allow for turning it into a blocking command. ### Understanding blocking - + `BLOCK` is one of the optional parameters that could be passed in to the `XREAD` command. - Without blocking, the current implementation of our command is synchronous. This means that the command can get new data as long as there are items available. + Without blocking, the current implementation of our command is synchronous. This means that the command can get new data as long as there are items available. If we want to wait for new data coming in, we need blocking. - Here's how it works. Let's use the entries previously shown as an example. + Here's how it works. + + Let's use the entries previously shown as an example. ```yaml - - 1526985054069-0 # (ID of the first entry) - temperature: 36 # (A key value pair in the first entry) - humidity: 95 # (Another key value pair in the first entry) + entries: + - id: 1526985054069-0 # (ID of the first entry) + temperature: 36 # (A key value pair in the first entry) + humidity: 95 # (Another key value pair in the first entry) - - 1526985054079-0 # (ID of the second entry) - temperature: 37 # (A key value pair in the first entry) - humidity: 94 # (Another key value pair in the first entry) + - id: 1526985054079-0 # (ID of the second entry) + temperature: 37 # (A key value pair in the first entry) + humidity: 94 # (Another key value pair in the first entry) - # ... (and so on) + # ... (and so on) ``` On one instance of the redis-cli, we'd add an entry and send a blocking `XREAD` command. ```bash - $ redis-cli xadd some_key 1526985054069-0 temperature 36 humidity 95 + $ redis-cli XADD some_key 1526985054069-0 temperature 36 humidity 95 "1526985054069-0" - $ redis-cli xread block 1000 streams some_key 1526985054069-0 + $ redis-cli XREAD block 1000 streams some_key 1526985054069-0 ``` Then, on another instance of the redis-cli, we add another entry. ```bash - $ other-redis-cli xadd some_key 1526985054079-0 temperature 37 humidity 94 + $ other-redis-cli XADD some_key 1526985054079-0 temperature 37 humidity 94 "1526985054079-0" ``` If the command was sent within 1000 milliseconds, the redis-cli will respond with the added entry. ```bash - $ redis-cli xadd some_key 1526985054069-0 temperature 36 humidity 95 + $ redis-cli XADD some_key 1526985054069-0 temperature 36 humidity 95 "1526985054069-0" - $ redis-cli xread block 1000 streams some_key 1526985054069-0 + $ redis-cli XREAD block 1000 streams some_key 1526985054069-0 1) 1) "some_key" 2) 1) 1) 1526985054079-0 2) 1) temperature @@ -2386,12 +2631,12 @@ stages: 4) 94 ``` - If not, the response would be nil encoded as a bulk string. + If not, the response would be a null representation of a bulk string. ```bash - $ redis-cli xadd some_key 1526985054069-0 temperature 36 humidity 95 + $ redis-cli XADD some_key 1526985054069-0 temperature 36 humidity 95 "1526985054069-0" - $ redis-cli xread block 1000 streams some_key 1526985054069-0 + $ redis-cli XREAD block 1000 streams some_key 1526985054069-0 (nil) ``` @@ -2406,19 +2651,19 @@ stages: First, an entry will be added to a stream. ```bash - $ redis-cli xadd stream_key 0-1 temperature 96 + $ redis-cli XADD stream_key 0-1 temperature 96 ``` It'll then send an `XREAD` command to your server with the `BLOCK` command. ```bash - $ redis-cli xread block 1000 streams stream_key 0-0 + $ redis-cli XREAD block 1000 streams stream_key 0-1 ``` On another instance of the redis-cli, another entry will be added in 500 milliseconds after sending the `XREAD` command. ```bash - $ redis-cli xadd stream_key 0-2 temperature 95 + $ redis-cli XADD stream_key 0-2 temperature 95 ``` Your server should respond with the following: @@ -2435,13 +2680,30 @@ stages: $3\r\n96\r\n ``` - This is the RESP encoded representation of `[["stream_key", ["0-2", ["temperature", "96"]]]]`. It'll send another `XREAD` command to your server with the `BLOCK` command but this time, it'll wait for 2000 milliseconds before checking the response of your server. + This is the RESP encoded representation of the following. + + ```json + [ + [ + "stream_key", + [ + "0-2", + [ + "temperature", + "96" + ] + ] + ] + ] + ``` + + It'll send another `XREAD` command to your server with the `BLOCK` command but this time, it'll wait for 2000 milliseconds before checking the response of your server. ```bash - $ redis-cli xread block 1000 streams stream_key 0-2 + $ redis-cli XREAD block 1000 streams stream_key 0-2 ``` - Your server should respond with `$3\r\nnil\r\n` which is nil RESP encoded as a bulk string. + Your server should respond with `$-1\r\n` which is a `null` representation of a RESP bulk string. ### Notes - In the response, the items are separated onto new lines for readability. The tester expects all of these to be in one line. @@ -2450,48 +2712,51 @@ stages: - slug: "streams-xread-block-no-timeout" primary_extension_slug: "streams" - name: "Support blocking reads without timeout" + name: "Blocking reads without timeout" difficulty: medium description_md: | - In this stage, you'll add extend support to `XREAD` to allow for the blocking command not timing out. + In this stage, you'll extend support to `XREAD` to allow for the blocking command not timing out. - ### Understandign blocking without timeout - - Here's how it works. Let's use the entries previously shown as an example. + ### Understanding blocking without timeout + + Here's how it works. + + Let's use the entries previously shown as an example. ```yaml - - 1526985054069-0 # (ID of the first entry) - temperature: 36 # (A key value pair in the first entry) - humidity: 95 # (Another key value pair in the first entry) + entries: + - id: 1526985054069-0 # (ID of the first entry) + temperature: 36 # (A key value pair in the first entry) + humidity: 95 # (Another key value pair in the first entry) - - 1526985054079-0 # (ID of the second entry) - temperature: 37 # (A key value pair in the first entry) - humidity: 94 # (Another key value pair in the first entry) + - id: 1526985054079-0 # (ID of the second entry) + temperature: 37 # (A key value pair in the first entry) + humidity: 94 # (Another key value pair in the first entry) - # ... (and so on) + # ... (and so on) ``` On one instance of the redis-cli, we'd add an entry and send a blocking `XREAD` command with 0 as the time passed in. ```bash - $ redis-cli xadd some_key 1526985054069-0 temperature 36 humidity 95 + $ redis-cli XADD some_key 1526985054069-0 temperature 36 humidity 95 "1526985054069-0" - $ redis-cli xread block 1000 streams some_key 1526985054069-0 + $ redis-cli XREAD block 0 streams some_key 1526985054069-0 ``` Then, on another instance of the redis-cli, we add another entry. ```bash - $ other-redis-cli xadd some_key 1526985054079-0 temperature 37 humidity 94 + $ other-redis-cli XADD some_key 1526985054079-0 temperature 37 humidity 94 "1526985054079-0" ``` - The difference now is that the first instance of the redis-cli doesn't time out and responds with nil no matter how much time passes. It will wait until another entry is added. The return value after an entry is added is similar to the last stage. + The difference now is that the first instance of the redis-cli doesn't time out and responds with null no matter how much time passes. It will wait until another entry is added. The return value after an entry is added is similar to the last stage. ```bash - $ redis-cli xadd some_key 1526985054069-0 temperature 36 humidity 95 + $ redis-cli XADD some_key 1526985054069-0 temperature 36 humidity 95 "1526985054069-0" - $ redis-cli xread block 1000 streams some_key 1526985054069-0 + $ redis-cli XREAD block 0 streams some_key 1526985054069-0 1) 1) "some_key" 2) 1) 1) 1526985054079-0 2) 1) temperature @@ -2511,19 +2776,19 @@ stages: First, an entry will be added to a stream. ```bash - $ redis-cli xadd stream_key 0-1 temperature 96 + $ redis-cli XADD stream_key 0-1 temperature 96 ``` It'll then send an `XREAD` command to your server with the `BLOCK` command with the time passed in being 0. ```bash - $ redis-cli xread block 0 streams stream_key 0-0 + $ redis-cli XREAD block 0 streams stream_key 0-0 ``` It'll then wait for 1000 milliseconds before checking if there is a response. Your server should not have a new response. It'll then add another entry. ```bash - $ redis-cli xadd stream_key 0-2 temperature 95 + $ redis-cli XADD stream_key 0-2 temperature 95 ``` Your server should respond with the following: @@ -2540,7 +2805,22 @@ stages: $3\r\n95\r\n ``` - This is the RESP encoded representation of `[["stream_key", ["0-2", ["temperature", "95"]]]]`. + This is the RESP encoded representation of the following. + + ```json + [ + [ + "stream_key", + [ + "0-2", + [ + "temperature", + "95" + ] + ] + ] + ] + ``` ### Notes - In the response, the items are separated onto new lines for readability. The tester expects all of these to be in one line. @@ -2549,50 +2829,53 @@ stages: - slug: "streams-xread-block-max-id" primary_extension_slug: "streams" - name: "Support blocking reads using $" + name: "Blocking reads using $" difficulty: easy description_md: | - In this stage, you'll add extend support to `XREAD` to allow for passing in `$` as the ID for a blocking command. + In this stage, you'll extend support to `XREAD` to allow for passing in `$` as the ID for a blocking command. ### Understanding $ Using `$` as the ID passed to a blocking `XREAD` command signals that we only want new entries. This is similar to passing in the maximum ID we currently have in the stream. - Here's how it works. Let's use the entries previously shown as an example. + Here's how it works. + + Let's use the entries previously shown as an example. ```yaml - - 1526985054069-0 # (ID of the first entry) - temperature: 36 # (A key value pair in the first entry) - humidity: 95 # (Another key value pair in the first entry) + entries: + - id: 1526985054069-0 # (ID of the first entry) + temperature: 36 # (A key value pair in the first entry) + humidity: 95 # (Another key value pair in the first entry) - - 1526985054079-0 # (ID of the second entry) - temperature: 37 # (A key value pair in the first entry) - humidity: 94 # (Another key value pair in the first entry) + - id: 1526985054079-0 # (ID of the second entry) + temperature: 37 # (A key value pair in the first entry) + humidity: 94 # (Another key value pair in the first entry) - # ... (and so on) + # ... (and so on) ``` - On one instance of the redis-cli, we'd add an entry and send a blocking `XREAD` command with 0 as the time passed in. + On one instance of the redis-cli, we'd add an entry and send a blocking `XREAD` command with `1000` as the time passed in and `$` as the id passed in. ```bash - $ redis-cli xadd some_key 1526985054069-0 temperature 36 humidity 95 + $ redis-cli XADD some_key 1526985054069-0 temperature 36 humidity 95 "1526985054069-0" - $ redis-cli xread block 1000 streams some_key $ + $ redis-cli XREAD block 1000 streams some_key $ ``` Then, on another instance of the redis-cli, we add another entry. ```bash - $ other-redis-cli xadd some_key 1526985054079-0 temperature 37 humidity 94 + $ other-redis-cli XADD some_key 1526985054079-0 temperature 37 humidity 94 "1526985054079-0" ``` Similar to the behavior detailed in the earlier stages, if the command was sent within 1000 milliseconds, the redis-cli will respond with the new entry. ```bash - $ redis-cli xadd some_key 1526985054069-0 temperature 36 humidity 95 + $ redis-cli XADD some_key 1526985054069-0 temperature 36 humidity 95 "1526985054069-0" - $ redis-cli xread block 1000 streams some_key 1526985054069-0 + $ redis-cli XREAD block 1000 streams some_key 1526985054069-0 1) 1) "some_key" 2) 1) 1) 1526985054079-0 2) 1) temperature @@ -2601,12 +2884,12 @@ stages: 4) 94 ``` - If not, the return type would still nil encoded as a bulk string. + If not, the return type would still be a null representation of a bulk string. ```bash - $ redis-cli xadd some_key 1526985054069-0 temperature 36 humidity 95 + $ redis-cli XADD some_key 1526985054069-0 temperature 36 humidity 95 "1526985054069-0" - $ redis-cli xread block 1000 streams some_key 1526985054069-0 + $ redis-cli XREAD block 1000 streams some_key 1526985054069-0 (nil) ``` @@ -2621,19 +2904,19 @@ stages: First, an entry will be added to a stream. ```bash - $ redis-cli xadd stream_key 0-1 temperature 96 + $ redis-cli XADD stream_key 0-1 temperature 96 ``` - It'll then send an `XREAD` command to your server with the `BLOCK` command with `$` as the ID. + It'll then send an `XREAD` command to your server with the `BLOCK` command with `0` as the time and `$` as the ID. ```bash - $ redis-cli xread block 0 streams stream_key $ + $ redis-cli XREAD block 0 streams stream_key $ ``` On another instance of the redis-cli, another entry will be added in 500 milliseconds after sending the `XREAD` command. ```bash - $ redis-cli xadd stream_key 0-2 temperature 95 + $ redis-cli XADD stream_key 0-2 temperature 95 ``` Your server should respond with the following: @@ -2650,13 +2933,30 @@ stages: $3\r\n96\r\n ``` - This is the RESP encoded representation of `[["stream_key", ["0-2", ["temperature", "95"]]]]`. It'll send another `XREAD` command to your server with the `BLOCK` command but this time, it'll wait for 2000 milliseconds before checking the response of your server. + This is the RESP encoded representation of the following. + + ```json + [ + [ + "stream_key", + [ + "0-2", + [ + "temperature", + "95" + ] + ] + ] + ] + ``` + + It'll send another `XREAD` command to your server with the `BLOCK` command but this time, it'll wait for 2000 milliseconds before checking the response of your server. ```bash - $ redis-cli xread block 1000 streams stream_key $ + $ redis-cli XREAD block 1000 streams stream_key $ ``` - Your server should respond with `$3\r\nnil\r\n` which is a `nil` encoded as a RESP bulk string. + Your server should respond with `$-1\r\n` which is a `null` representation of a RESP bulk string. ### Notes - In the response, the items are separated onto new lines for readability. The tester expects all of these to be in one line. diff --git a/internal/test_helpers/fixtures/rdb-read-value-with-expiry/pass b/internal/test_helpers/fixtures/rdb-read-value-with-expiry/pass index c7a3020..709cfa1 100644 --- a/internal/test_helpers/fixtures/rdb-read-value-with-expiry/pass +++ b/internal/test_helpers/fixtures/rdb-read-value-with-expiry/pass @@ -1,7 +1,7 @@ Debug = true [stage-13] Running tests for Stage #13: rdb-read-value-with-expiry -[stage-13] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2171702849 --dbfilename pear.rdb +[stage-13] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3027591544 --dbfilename pear.rdb [stage-13] client: $ redis-cli GET orange [stage-13] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$6\r\norange\r\n" [stage-13] client: Received bytes: "$10\r\nstrawberry\r\n" @@ -23,7 +23,7 @@ Debug = true [stage-12] Running tests for Stage #12: rdb-read-multiple-string-values [stage-12] Created RDB file with key-value pairs: "grape"="pineapple", "apple"="raspberry", "banana"="apple", "mango"="orange", "orange"="pear" -[stage-12] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2693035745 --dbfilename raspberry.rdb +[stage-12] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles4230549431 --dbfilename raspberry.rdb [stage-12] client: $ redis-cli GET grape [stage-12] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\ngrape\r\n" [stage-12] client: Received bytes: "$9\r\npineapple\r\n" @@ -55,19 +55,19 @@ Debug = true [stage-11] Running tests for Stage #11: rdb-read-multiple-keys [stage-11] Created RDB file with 3 keys: ["banana" "apple" "blueberry"] -[stage-11] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2343972202 --dbfilename blueberry.rdb +[stage-11] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1567495839 --dbfilename blueberry.rdb [stage-11] client: $ redis-cli KEYS * [stage-11] client: Sent bytes: "*2\r\n$4\r\nKEYS\r\n$1\r\n*\r\n" -[stage-11] client: Received bytes: "*3\r\n$6\r\nbanana\r\n$9\r\nblueberry\r\n$5\r\napple\r\n" -[stage-11] client: Received RESP value: ["banana", "blueberry", "apple"] -[stage-11] Received ["banana", "blueberry", "apple"] +[stage-11] client: Received bytes: "*3\r\n$5\r\napple\r\n$6\r\nbanana\r\n$9\r\nblueberry\r\n" +[stage-11] client: Received RESP value: ["apple", "banana", "blueberry"] +[stage-11] Received ["apple", "banana", "blueberry"] [stage-11] Test passed. [stage-11] Terminating program [stage-11] Program terminated successfully [stage-10] Running tests for Stage #10: rdb-read-string-value [stage-10] Created RDB file with single key-value pair: grape="pineapple" -[stage-10] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2430917994 --dbfilename orange.rdb +[stage-10] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles775229267 --dbfilename orange.rdb [stage-10] client: $ redis-cli GET grape [stage-10] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\ngrape\r\n" [stage-10] client: Received bytes: "$9\r\npineapple\r\n" @@ -79,7 +79,7 @@ Debug = true [stage-9] Running tests for Stage #9: rdb-read-key [stage-9] Created RDB file with single key: "mango" -[stage-9] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles137626249 --dbfilename pear.rdb +[stage-9] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1527972385 --dbfilename pear.rdb [stage-9] client: $ redis-cli KEYS * [stage-9] client: Sent bytes: "*2\r\n$4\r\nKEYS\r\n$1\r\n*\r\n" [stage-9] client: Received bytes: "*1\r\n$5\r\nmango\r\n" @@ -90,12 +90,12 @@ Debug = true [stage-9] Program terminated successfully [stage-8] Running tests for Stage #8: rdb-config -[stage-8] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1388308438 --dbfilename blueberry.rdb +[stage-8] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1821958071 --dbfilename blueberry.rdb [stage-8] client: $ redis-cli CONFIG GET dir [stage-8] client: Sent bytes: "*3\r\n$6\r\nCONFIG\r\n$3\r\nGET\r\n$3\r\ndir\r\n" -[stage-8] client: Received bytes: "*2\r\n$3\r\ndir\r\n$75\r\n/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1388308438\r\n" -[stage-8] client: Received RESP value: ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1388308438"] -[stage-8] Received ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1388308438"] +[stage-8] client: Received bytes: "*2\r\n$3\r\ndir\r\n$75\r\n/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1821958071\r\n" +[stage-8] client: Received RESP value: ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1821958071"] +[stage-8] Received ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1821958071"] [stage-8] Test passed. [stage-8] Terminating program [stage-8] Program terminated successfully @@ -107,15 +107,15 @@ Debug = true [stage-7] Received bytes: "+OK\r\n" [stage-7] Received RESP value: "OK" [stage-7] Received "OK" -[stage-7] Received OK at 19:16:17.030 -[stage-7] Fetching key "strawberry" at 19:16:17.030 (should not be expired) +[stage-7] Received OK at 21:36:24.124 +[stage-7] Fetching key "strawberry" at 21:36:24.124 (should not be expired) [stage-7] $ redis-cli GET strawberry [stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$10\r\nstrawberry\r\n" [stage-7] Received bytes: "$4\r\npear\r\n" [stage-7] Received RESP value: "pear" [stage-7] Received "pear" [stage-7] Sleeping for 101ms -[stage-7] Fetching key "strawberry" at 19:16:17.134 (should be expired) +[stage-7] Fetching key "strawberry" at 21:36:24.227 (should be expired) [stage-7] $ redis-cli GET strawberry [stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$10\r\nstrawberry\r\n" [stage-7] Received bytes: "$-1\r\n" diff --git a/internal/test_helpers/fixtures/repl-wait/pass b/internal/test_helpers/fixtures/repl-wait/pass index d8b146d..a152992 100644 --- a/internal/test_helpers/fixtures/repl-wait/pass +++ b/internal/test_helpers/fixtures/repl-wait/pass @@ -21,11 +21,11 @@ Debug = true [stage-31] Received "OK" [stage-31] replica-1: $ redis-cli PSYNC ? -1 [stage-31] replica-1: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-31] replica-1: Received bytes: "+FULLRESYNC 22ddf55287906049f067448d2863815fe3752a60 0\r\n" -[stage-31] replica-1: Received RESP value: "FULLRESYNC 22ddf55287906049f067448d2863815fe3752a60 0" -[stage-31] Received "FULLRESYNC 22ddf55287906049f067448d2863815fe3752a60 0" +[stage-31] replica-1: Received bytes: "+FULLRESYNC 27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2 0\r\n" +[stage-31] replica-1: Received RESP value: "FULLRESYNC 27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2 0" +[stage-31] Received "FULLRESYNC 27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2 0" [stage-31] Reading RDB file... -[stage-31] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xe9D>f\xfa\bused-mem\xc2P\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(22ddf55287906049f067448d2863815fe3752a60\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x9ds\xf3`\x82\v\xc4\xd2" +[stage-31] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xe8G>f\xfa\bused-mem\xc20\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xe6Xv,\xf5\xe2\x05\x14" [stage-31] Received RDB file [stage-31] Creating replica: 2 [stage-31] replica-2: $ redis-cli PING @@ -45,11 +45,11 @@ Debug = true [stage-31] Received "OK" [stage-31] replica-2: $ redis-cli PSYNC ? -1 [stage-31] replica-2: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-31] replica-2: Received bytes: "+FULLRESYNC 22ddf55287906049f067448d2863815fe3752a60 0\r\n" -[stage-31] replica-2: Received RESP value: "FULLRESYNC 22ddf55287906049f067448d2863815fe3752a60 0" -[stage-31] Received "FULLRESYNC 22ddf55287906049f067448d2863815fe3752a60 0" +[stage-31] replica-2: Received bytes: "+FULLRESYNC 27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2 0\r\n" +[stage-31] replica-2: Received RESP value: "FULLRESYNC 27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2 0" +[stage-31] Received "FULLRESYNC 27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2 0" [stage-31] Reading RDB file... -[stage-31] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xe9D>f\xfa\bused-mem\xc2\xe0\xb9\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(22ddf55287906049f067448d2863815fe3752a60\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffQ\f\xb6ӓ\x93O\xfa" +[stage-31] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xe8G>f\xfa\bused-mem\xc2\xc0\xf5\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffOM\xe1+\rOˡ" [stage-31] Received RDB file [stage-31] Creating replica: 3 [stage-31] replica-3: $ redis-cli PING @@ -69,11 +69,11 @@ Debug = true [stage-31] Received "OK" [stage-31] replica-3: $ redis-cli PSYNC ? -1 [stage-31] replica-3: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-31] replica-3: Received bytes: "+FULLRESYNC 22ddf55287906049f067448d2863815fe3752a60 0\r\n" -[stage-31] replica-3: Received RESP value: "FULLRESYNC 22ddf55287906049f067448d2863815fe3752a60 0" -[stage-31] Received "FULLRESYNC 22ddf55287906049f067448d2863815fe3752a60 0" +[stage-31] replica-3: Received bytes: "+FULLRESYNC 27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2 0\r\n" +[stage-31] replica-3: Received RESP value: "FULLRESYNC 27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2 0" +[stage-31] Received "FULLRESYNC 27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2 0" [stage-31] Reading RDB file... -[stage-31] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xeaD>f\xfa\bused-mem\xc2\xe0@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(22ddf55287906049f067448d2863815fe3752a60\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x9a*\xb2\x8cST\x85\xec" +[stage-31] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xe8G>f\xfa\bused-mem\xc2\xc0@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffwjyc\xe4\x80\\\x8f" [stage-31] Received RDB file [stage-31] Creating replica: 4 [stage-31] replica-4: $ redis-cli PING @@ -93,11 +93,11 @@ Debug = true [stage-31] Received "OK" [stage-31] replica-4: $ redis-cli PSYNC ? -1 [stage-31] replica-4: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-31] replica-4: Received bytes: "+FULLRESYNC 22ddf55287906049f067448d2863815fe3752a60 0\r\n" -[stage-31] replica-4: Received RESP value: "FULLRESYNC 22ddf55287906049f067448d2863815fe3752a60 0" -[stage-31] Received "FULLRESYNC 22ddf55287906049f067448d2863815fe3752a60 0" +[stage-31] replica-4: Received bytes: "+FULLRESYNC 27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2 0\r\n" +[stage-31] replica-4: Received RESP value: "FULLRESYNC 27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2 0" +[stage-31] Received "FULLRESYNC 27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2 0" [stage-31] Reading RDB file... -[stage-31] replica-4: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xeaD>f\xfa\bused-mem\xc2\xf0\x8b\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(22ddf55287906049f067448d2863815fe3752a60\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff^\x1f3\xfbE.\x90D" +[stage-31] replica-4: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xe8G>f\xfa\bused-mem\xc2Ћ\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(27f339d71e7e0b0ab4439c97b65da9acf3b2b0c2\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xb3_\xf8\x14\xf2\xfaI'" [stage-31] Received RDB file [stage-31] client: $ redis-cli SET foo 123 [stage-31] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" @@ -214,7 +214,7 @@ Debug = true [stage-31] replica-4: Not sending ACK to Master [stage-31] client: Received bytes: ":3\r\n" [stage-31] client: Received RESP value: 3 -[stage-31] WAIT command returned after 2098 ms +[stage-31] WAIT command returned after 2104 ms [stage-31] Test passed. [stage-31] Terminating program [stage-31] Program terminated successfully @@ -240,11 +240,11 @@ Debug = true [stage-30] Received "OK" [stage-30] replica-1: $ redis-cli PSYNC ? -1 [stage-30] replica-1: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-30] replica-1: Received bytes: "+FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0\r\n" -[stage-30] replica-1: Received RESP value: "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" -[stage-30] Received "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" +[stage-30] replica-1: Received bytes: "+FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0\r\n" +[stage-30] replica-1: Received RESP value: "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" +[stage-30] Received "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" [stage-30] Reading RDB file... -[stage-30] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xecD>f\xfa\bused-mem\xc2P\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(0216b41129aceba87fc234640ab89973de310c58\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff)\x87P\x8ap\xa7\xea\x9f" +[stage-30] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xeaG>f\xfa\bused-mem\xc20\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(8cd14a6c81272bb3a43b385ffd61fde3e79b51dc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffI#\xae\xa1|\x85\xbch" [stage-30] Received RDB file [stage-30] Creating replica: 2 [stage-30] replica-2: $ redis-cli PING @@ -264,11 +264,11 @@ Debug = true [stage-30] Received "OK" [stage-30] replica-2: $ redis-cli PSYNC ? -1 [stage-30] replica-2: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-30] replica-2: Received bytes: "+FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0\r\n" -[stage-30] replica-2: Received RESP value: "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" -[stage-30] Received "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" +[stage-30] replica-2: Received bytes: "+FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0\r\n" +[stage-30] replica-2: Received RESP value: "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" +[stage-30] Received "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" [stage-30] Reading RDB file... -[stage-30] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xecD>f\xfa\bused-mem\xc2\xe0\xf5\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(0216b41129aceba87fc234640ab89973de310c58\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffbt\xf7\xda\x16Þ\xc6" +[stage-30] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xeaG>f\xfa\bused-mem\xc2\xc0\xf5\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(8cd14a6c81272bb3a43b385ffd61fde3e79b51dc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xe069\xa6\x84(r\xdd" [stage-30] Received RDB file [stage-30] Creating replica: 3 [stage-30] replica-3: $ redis-cli PING @@ -288,11 +288,11 @@ Debug = true [stage-30] Received "OK" [stage-30] replica-3: $ redis-cli PSYNC ? -1 [stage-30] replica-3: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-30] replica-3: Received bytes: "+FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0\r\n" -[stage-30] replica-3: Received RESP value: "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" -[stage-30] Received "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" +[stage-30] replica-3: Received bytes: "+FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0\r\n" +[stage-30] replica-3: Received RESP value: "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" +[stage-30] Received "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" [stage-30] Reading RDB file... -[stage-30] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xecD>f\xfa\bused-mem\xc2\xe0@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(0216b41129aceba87fc234640ab89973de310c58\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffZSo\x92\xff\f\t\xe8" +[stage-30] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xeaG>f\xfa\bused-mem\xc2\xc0@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(8cd14a6c81272bb3a43b385ffd61fde3e79b51dc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xd8\x11\xa1\xeem\xe7\xe5\xf3" [stage-30] Received RDB file [stage-30] Creating replica: 4 [stage-30] replica-4: $ redis-cli PING @@ -312,11 +312,11 @@ Debug = true [stage-30] Received "OK" [stage-30] replica-4: $ redis-cli PSYNC ? -1 [stage-30] replica-4: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-30] replica-4: Received bytes: "+FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0\r\n" -[stage-30] replica-4: Received RESP value: "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" -[stage-30] Received "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" +[stage-30] replica-4: Received bytes: "+FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0\r\n" +[stage-30] replica-4: Received RESP value: "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" +[stage-30] Received "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" [stage-30] Reading RDB file... -[stage-30] replica-4: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xecD>f\xfa\bused-mem\xc2\xf0\x8b\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(0216b41129aceba87fc234640ab89973de310c58\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x9ef\xee\xe5\xe9v\x1c@" +[stage-30] replica-4: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xebG>f\xfa\bused-mem\xc2Ћ\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(8cd14a6c81272bb3a43b385ffd61fde3e79b51dc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xe9\xd1x\xfd\x80,\xa6\x85" [stage-30] Received RDB file [stage-30] Creating replica: 5 [stage-30] replica-5: $ redis-cli PING @@ -336,11 +336,11 @@ Debug = true [stage-30] Received "OK" [stage-30] replica-5: $ redis-cli PSYNC ? -1 [stage-30] replica-5: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-30] replica-5: Received bytes: "+FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0\r\n" -[stage-30] replica-5: Received RESP value: "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" -[stage-30] Received "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" +[stage-30] replica-5: Received bytes: "+FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0\r\n" +[stage-30] replica-5: Received RESP value: "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" +[stage-30] Received "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" [stage-30] Reading RDB file... -[stage-30] replica-5: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xecD>f\xfa\bused-mem\xc2\x00\xd7\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(0216b41129aceba87fc234640ab89973de310c58\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xe7w\x12\x1c\xa1\xf6Z\xdb" +[stage-30] replica-5: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xebG>f\xfa\bused-mem\xc2\xe0\xd6\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(8cd14a6c81272bb3a43b385ffd61fde3e79b51dc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xe8V9\x10\xb5\x9cv\xcf" [stage-30] Received RDB file [stage-30] Creating replica: 6 [stage-30] replica-6: $ redis-cli PING @@ -360,11 +360,11 @@ Debug = true [stage-30] Received "OK" [stage-30] replica-6: $ redis-cli PSYNC ? -1 [stage-30] replica-6: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-30] replica-6: Received bytes: "+FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0\r\n" -[stage-30] replica-6: Received RESP value: "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" -[stage-30] Received "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" +[stage-30] replica-6: Received bytes: "+FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0\r\n" +[stage-30] replica-6: Received RESP value: "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" +[stage-30] Received "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" [stage-30] Reading RDB file... -[stage-30] replica-6: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xecD>f\xfa\bused-mem\xc2\x00\"\x14\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(0216b41129aceba87fc234640ab89973de310c58\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x8a\xc2\xd3\xf5K\x17Sn" +[stage-30] replica-6: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xebG>f\xfa\bused-mem\xc2\x10#\x14\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(8cd14a6c81272bb3a43b385ffd61fde3e79b51dc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xb4\xd8!J/D6\xbc" [stage-30] Received RDB file [stage-30] Creating replica: 7 [stage-30] replica-7: $ redis-cli PING @@ -384,11 +384,11 @@ Debug = true [stage-30] Received "OK" [stage-30] replica-7: $ redis-cli PSYNC ? -1 [stage-30] replica-7: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-30] replica-7: Received bytes: "+FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0\r\n" -[stage-30] replica-7: Received RESP value: "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" -[stage-30] Received "FULLRESYNC 0216b41129aceba87fc234640ab89973de310c58 0" +[stage-30] replica-7: Received bytes: "+FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0\r\n" +[stage-30] replica-7: Received RESP value: "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" +[stage-30] Received "FULLRESYNC 8cd14a6c81272bb3a43b385ffd61fde3e79b51dc 0" [stage-30] Reading RDB file... -[stage-30] replica-7: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xedD>f\xfa\bused-mem\xc2\x10m\x14\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(0216b41129aceba87fc234640ab89973de310c58\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xc1\xaa\xf4\xccO\x88!\x15" +[stage-30] replica-7: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xebG>f\xfa\bused-mem\xc2 n\x14\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(8cd14a6c81272bb3a43b385ffd61fde3e79b51dc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffz\xf9\xa7\x0eU\xb1\x16\xda" [stage-30] Received RDB file [stage-30] client: $ redis-cli WAIT 3 500 [stage-30] client: Sent bytes: "*3\r\n$4\r\nWAIT\r\n$1\r\n3\r\n$3\r\n500\r\n" @@ -427,7 +427,7 @@ Debug = true [stage-28] Running tests for Stage #28: repl-replica-getack-nonzero [stage-28] Master is running on port 6379 -[stage-28] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-28] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-28] master: Waiting for replica to initiate handshake with "PING" command [stage-28] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-28] master: Received RESP value: ["PING"] @@ -482,7 +482,7 @@ Debug = true [stage-27] Running tests for Stage #27: repl-replica-getack [stage-27] Master is running on port 6379 -[stage-27] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-27] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-27] master: Waiting for replica to initiate handshake with "PING" command [stage-27] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-27] master: Received RESP value: ["PING"] @@ -521,7 +521,7 @@ Debug = true [stage-26] Running tests for Stage #26: repl-cmd-processing [stage-26] Master is running on port 6379 -[stage-26] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-26] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-26] master: Waiting for replica to initiate handshake with "PING" command [stage-26] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-26] master: Received RESP value: ["PING"] @@ -597,11 +597,11 @@ Debug = true [stage-25] Received "OK" [stage-25] replica-1: $ redis-cli PSYNC ? -1 [stage-25] replica-1: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-25] replica-1: Received bytes: "+FULLRESYNC f3269d13cbba21520746a0dcfd83a55c690b8e06 0\r\n" -[stage-25] replica-1: Received RESP value: "FULLRESYNC f3269d13cbba21520746a0dcfd83a55c690b8e06 0" -[stage-25] Received "FULLRESYNC f3269d13cbba21520746a0dcfd83a55c690b8e06 0" +[stage-25] replica-1: Received bytes: "+FULLRESYNC b8512b711c89467776abd880b8206d999b5bc5cc 0\r\n" +[stage-25] replica-1: Received RESP value: "FULLRESYNC b8512b711c89467776abd880b8206d999b5bc5cc 0" +[stage-25] Received "FULLRESYNC b8512b711c89467776abd880b8206d999b5bc5cc 0" [stage-25] Reading RDB file... -[stage-25] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xeeD>f\xfa\bused-mem\xc2\x00S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(f3269d13cbba21520746a0dcfd83a55c690b8e06\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xf9\xbc\xe8\x1c\xf6\xa3@Q" +[stage-25] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xecG>f\xfa\bused-mem\xc2 S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(b8512b711c89467776abd880b8206d999b5bc5cc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xf5\xa8\x15\x1d\x8dعA" [stage-25] Received RDB file [stage-25] Creating replica: 2 [stage-25] replica-2: $ redis-cli PING @@ -621,11 +621,11 @@ Debug = true [stage-25] Received "OK" [stage-25] replica-2: $ redis-cli PSYNC ? -1 [stage-25] replica-2: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-25] replica-2: Received bytes: "+FULLRESYNC f3269d13cbba21520746a0dcfd83a55c690b8e06 0\r\n" -[stage-25] replica-2: Received RESP value: "FULLRESYNC f3269d13cbba21520746a0dcfd83a55c690b8e06 0" -[stage-25] Received "FULLRESYNC f3269d13cbba21520746a0dcfd83a55c690b8e06 0" +[stage-25] replica-2: Received bytes: "+FULLRESYNC b8512b711c89467776abd880b8206d999b5bc5cc 0\r\n" +[stage-25] replica-2: Received RESP value: "FULLRESYNC b8512b711c89467776abd880b8206d999b5bc5cc 0" +[stage-25] Received "FULLRESYNC b8512b711c89467776abd880b8206d999b5bc5cc 0" [stage-25] Reading RDB file... -[stage-25] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xeeD>f\xfa\bused-mem\xc2p:\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(f3269d13cbba21520746a0dcfd83a55c690b8e06\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x04q\xd0M\x16UfZ" +[stage-25] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xecG>f\xfa\bused-mem\u0090:\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(b8512b711c89467776abd880b8206d999b5bc5cc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffE\xdd\xeb\xed\x9cR\tT" [stage-25] Received RDB file [stage-25] Creating replica: 3 [stage-25] replica-3: $ redis-cli PING @@ -645,11 +645,11 @@ Debug = true [stage-25] Received "OK" [stage-25] replica-3: $ redis-cli PSYNC ? -1 [stage-25] replica-3: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-25] replica-3: Received bytes: "+FULLRESYNC f3269d13cbba21520746a0dcfd83a55c690b8e06 0\r\n" -[stage-25] replica-3: Received RESP value: "FULLRESYNC f3269d13cbba21520746a0dcfd83a55c690b8e06 0" -[stage-25] Received "FULLRESYNC f3269d13cbba21520746a0dcfd83a55c690b8e06 0" +[stage-25] replica-3: Received bytes: "+FULLRESYNC b8512b711c89467776abd880b8206d999b5bc5cc 0\r\n" +[stage-25] replica-3: Received RESP value: "FULLRESYNC b8512b711c89467776abd880b8206d999b5bc5cc 0" +[stage-25] Received "FULLRESYNC b8512b711c89467776abd880b8206d999b5bc5cc 0" [stage-25] Reading RDB file... -[stage-25] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xeeD>f\xfa\bused-mem\u0080I\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(f3269d13cbba21520746a0dcfd83a55c690b8e06\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffl\xdbE$NE\xa7 " +[stage-25] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xecG>f\xfa\bused-mem\u00a0I\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(b8512b711c89467776abd880b8206d999b5bc5cc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff`ϸ%5>^0" [stage-25] Received RDB file [stage-25] client: $ redis-cli SET foo 123 [stage-25] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" @@ -734,11 +734,11 @@ Debug = true [stage-24] Received "OK" [stage-24] replica: $ redis-cli PSYNC ? -1 [stage-24] replica: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-24] replica: Received bytes: "+FULLRESYNC 48827d4c3cce9445661af6b2e4215bd06de5e5d6 0\r\n" -[stage-24] replica: Received RESP value: "FULLRESYNC 48827d4c3cce9445661af6b2e4215bd06de5e5d6 0" -[stage-24] Received "FULLRESYNC 48827d4c3cce9445661af6b2e4215bd06de5e5d6 0" +[stage-24] replica: Received bytes: "+FULLRESYNC 1227420da59b3d0469c84bea9f1ea996ba2002b3 0\r\n" +[stage-24] replica: Received RESP value: "FULLRESYNC 1227420da59b3d0469c84bea9f1ea996ba2002b3 0" +[stage-24] Received "FULLRESYNC 1227420da59b3d0469c84bea9f1ea996ba2002b3 0" [stage-24] Reading RDB file... -[stage-24] replica: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xeeD>f\xfa\bused-mem\xc2\x00S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(48827d4c3cce9445661af6b2e4215bd06de5e5d6\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x11zE=9=\xd9(" +[stage-24] replica: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xedG>f\xfa\bused-mem\xc2@S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(1227420da59b3d0469c84bea9f1ea996ba2002b3\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xe9\x04\xdf{\x1e\x1dg)" [stage-24] Received RDB file [stage-24] client: $ redis-cli SET foo 123 [stage-24] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" @@ -793,11 +793,11 @@ Debug = true [stage-23] Received "OK" [stage-23] client: $ redis-cli PSYNC ? -1 [stage-23] client: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-23] client: Received bytes: "+FULLRESYNC ad1aff0518298ffe04cf2ded997f93060cf83b87 0\r\n" -[stage-23] client: Received RESP value: "FULLRESYNC ad1aff0518298ffe04cf2ded997f93060cf83b87 0" -[stage-23] Received "FULLRESYNC ad1aff0518298ffe04cf2ded997f93060cf83b87 0" +[stage-23] client: Received bytes: "+FULLRESYNC 0e2ea0806b83e800d32b9cf47c0e319d3e2d69f1 0\r\n" +[stage-23] client: Received RESP value: "FULLRESYNC 0e2ea0806b83e800d32b9cf47c0e319d3e2d69f1 0" +[stage-23] Received "FULLRESYNC 0e2ea0806b83e800d32b9cf47c0e319d3e2d69f1 0" [stage-23] Reading RDB file... -[stage-23] client: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xefD>f\xfa\bused-mem\xc2P\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(ad1aff0518298ffe04cf2ded997f93060cf83b87\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xfa'gg\xccO\x140" +[stage-23] client: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xedG>f\xfa\bused-mem\xc20\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(0e2ea0806b83e800d32b9cf47c0e319d3e2d69f1\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x12\xfbh)5ޛ\x1b" [stage-23] Received RDB file [stage-23] Test passed. [stage-23] Terminating program @@ -822,9 +822,9 @@ Debug = true [stage-22] Received "OK" [stage-22] client: $ redis-cli PSYNC ? -1 [stage-22] client: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-22] client: Received bytes: "+FULLRESYNC e521ef6bd07b94912cfb0f37a9a39d1eea8ea12d 0\r\n" -[stage-22] client: Received RESP value: "FULLRESYNC e521ef6bd07b94912cfb0f37a9a39d1eea8ea12d 0" -[stage-22] Received "FULLRESYNC e521ef6bd07b94912cfb0f37a9a39d1eea8ea12d 0" +[stage-22] client: Received bytes: "+FULLRESYNC deea264341bb6a3087235bad95d4488f97723f3a 0\r\n" +[stage-22] client: Received RESP value: "FULLRESYNC deea264341bb6a3087235bad95d4488f97723f3a 0" +[stage-22] Received "FULLRESYNC deea264341bb6a3087235bad95d4488f97723f3a 0" [stage-22] Test passed. [stage-22] Terminating program [stage-22] Program terminated successfully @@ -852,7 +852,7 @@ Debug = true [stage-20] Running tests for Stage #20: repl-replica-psync [stage-20] Master is running on port 6379 -[stage-20] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-20] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-20] master: Waiting for replica to initiate handshake with "PING" command [stage-20] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-20] master: Received RESP value: ["PING"] @@ -883,7 +883,7 @@ Debug = true [stage-19] Running tests for Stage #19: repl-replica-replconf [stage-19] Master is running on port 6379 -[stage-19] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-19] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-19] master: Waiting for replica to initiate handshake with "PING" command [stage-19] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-19] master: Received RESP value: ["PING"] @@ -908,7 +908,7 @@ Debug = true [stage-18] Running tests for Stage #18: repl-replica-ping [stage-18] Master is running on port 6379. -[stage-18] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-18] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-18] master: Waiting for replica to initiate handshake with "PING" command [stage-18] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-18] master: Received RESP value: ["PING"] @@ -923,9 +923,9 @@ Debug = true [stage-17] $ ./spawn_redis_server.sh [stage-17] client: $ redis-cli INFO replication [stage-17] client: Sent bytes: "*2\r\n$4\r\nINFO\r\n$11\r\nreplication\r\n" -[stage-17] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:734588b179806f518bf81fe9854727b6c21ee678\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" -[stage-17] client: Received RESP value: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:734588b179806f518bf81fe9854727b6c21ee678\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" -[stage-17] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:734588b179806f518bf81fe9854727b6c21ee678\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-17] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:1816f0bdd8e48a596542a34856f7974a6e075139\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" +[stage-17] client: Received RESP value: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:1816f0bdd8e48a596542a34856f7974a6e075139\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-17] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:1816f0bdd8e48a596542a34856f7974a6e075139\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" [stage-17] Found master_replid:xxx in response. [stage-17] Found master_reploffset:0 in response. [stage-17] Test passed. @@ -934,7 +934,7 @@ Debug = true [stage-16] Running tests for Stage #16: repl-info-replica [stage-16] Master is running on port 6379 -[stage-16] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-16] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-16] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-16] master: Received RESP value: ["PING"] [stage-16] master: Sent "PONG" @@ -966,9 +966,9 @@ Debug = true [stage-15] $ ./spawn_redis_server.sh [stage-15] client: $ redis-cli INFO replication [stage-15] client: Sent bytes: "*2\r\n$4\r\nINFO\r\n$11\r\nreplication\r\n" -[stage-15] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:260ce55c6990c54f2ff72d332815aa7368b1c86e\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" -[stage-15] client: Received RESP value: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:260ce55c6990c54f2ff72d332815aa7368b1c86e\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" -[stage-15] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:260ce55c6990c54f2ff72d332815aa7368b1c86e\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-15] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:9109cc3b41587024f9bdc7461eb8c90746e97421\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" +[stage-15] client: Received RESP value: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:9109cc3b41587024f9bdc7461eb8c90746e97421\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-15] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:9109cc3b41587024f9bdc7461eb8c90746e97421\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" [stage-15] Found role:master in response. [stage-15] Test passed. [stage-15] Terminating program @@ -983,7 +983,7 @@ Debug = true [stage-14] Program terminated successfully [stage-13] Running tests for Stage #13: rdb-read-value-with-expiry -[stage-13] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles4233821438 --dbfilename pear.rdb +[stage-13] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2414152642 --dbfilename pear.rdb [stage-13] client: $ redis-cli GET blueberry [stage-13] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$9\r\nblueberry\r\n" [stage-13] client: Received bytes: "$9\r\nblueberry\r\n" @@ -1005,7 +1005,7 @@ Debug = true [stage-12] Running tests for Stage #12: rdb-read-multiple-string-values [stage-12] Created RDB file with key-value pairs: "grape"="mango", "orange"="banana", "blueberry"="orange", "pear"="grape", "banana"="blueberry" -[stage-12] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles809326956 --dbfilename mango.rdb +[stage-12] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles902309970 --dbfilename mango.rdb [stage-12] client: $ redis-cli GET grape [stage-12] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\ngrape\r\n" [stage-12] client: Received bytes: "$5\r\nmango\r\n" @@ -1037,19 +1037,19 @@ Debug = true [stage-11] Running tests for Stage #11: rdb-read-multiple-keys [stage-11] Created RDB file with 4 keys: ["raspberry" "blueberry" "apple" "orange"] -[stage-11] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2703856200 --dbfilename grape.rdb +[stage-11] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles4069510286 --dbfilename grape.rdb [stage-11] client: $ redis-cli KEYS * [stage-11] client: Sent bytes: "*2\r\n$4\r\nKEYS\r\n$1\r\n*\r\n" -[stage-11] client: Received bytes: "*4\r\n$6\r\norange\r\n$5\r\napple\r\n$9\r\nblueberry\r\n$9\r\nraspberry\r\n" -[stage-11] client: Received RESP value: ["orange", "apple", "blueberry", "raspberry"] -[stage-11] Received ["orange", "apple", "blueberry", "raspberry"] +[stage-11] client: Received bytes: "*4\r\n$6\r\norange\r\n$9\r\nraspberry\r\n$5\r\napple\r\n$9\r\nblueberry\r\n" +[stage-11] client: Received RESP value: ["orange", "raspberry", "apple", "blueberry"] +[stage-11] Received ["orange", "raspberry", "apple", "blueberry"] [stage-11] Test passed. [stage-11] Terminating program [stage-11] Program terminated successfully [stage-10] Running tests for Stage #10: rdb-read-string-value [stage-10] Created RDB file with single key-value pair: blueberry="raspberry" -[stage-10] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3883532194 --dbfilename strawberry.rdb +[stage-10] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles4230954736 --dbfilename strawberry.rdb [stage-10] client: $ redis-cli GET blueberry [stage-10] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$9\r\nblueberry\r\n" [stage-10] client: Received bytes: "$9\r\nraspberry\r\n" @@ -1061,7 +1061,7 @@ Debug = true [stage-9] Running tests for Stage #9: rdb-read-key [stage-9] Created RDB file with single key: "grape" -[stage-9] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1845242451 --dbfilename orange.rdb +[stage-9] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2939135434 --dbfilename orange.rdb [stage-9] client: $ redis-cli KEYS * [stage-9] client: Sent bytes: "*2\r\n$4\r\nKEYS\r\n$1\r\n*\r\n" [stage-9] client: Received bytes: "*1\r\n$5\r\ngrape\r\n" @@ -1072,12 +1072,12 @@ Debug = true [stage-9] Program terminated successfully [stage-8] Running tests for Stage #8: rdb-config -[stage-8] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles760721523 --dbfilename raspberry.rdb +[stage-8] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles807335325 --dbfilename raspberry.rdb [stage-8] client: $ redis-cli CONFIG GET dir [stage-8] client: Sent bytes: "*3\r\n$6\r\nCONFIG\r\n$3\r\nGET\r\n$3\r\ndir\r\n" -[stage-8] client: Received bytes: "*2\r\n$3\r\ndir\r\n$74\r\n/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles760721523\r\n" -[stage-8] client: Received RESP value: ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles760721523"] -[stage-8] Received ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles760721523"] +[stage-8] client: Received bytes: "*2\r\n$3\r\ndir\r\n$74\r\n/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles807335325\r\n" +[stage-8] client: Received RESP value: ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles807335325"] +[stage-8] Received ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles807335325"] [stage-8] Test passed. [stage-8] Terminating program [stage-8] Program terminated successfully @@ -1089,15 +1089,15 @@ Debug = true [stage-7] Received bytes: "+OK\r\n" [stage-7] Received RESP value: "OK" [stage-7] Received "OK" -[stage-7] Received OK at 21:31:54.156 -[stage-7] Fetching key "mango" at 21:31:54.156 (should not be expired) +[stage-7] Received OK at 21:44:40.684 +[stage-7] Fetching key "mango" at 21:44:40.684 (should not be expired) [stage-7] $ redis-cli GET mango [stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\nmango\r\n" [stage-7] Received bytes: "$6\r\norange\r\n" [stage-7] Received RESP value: "orange" [stage-7] Received "orange" [stage-7] Sleeping for 101ms -[stage-7] Fetching key "mango" at 21:31:54.259 (should be expired) +[stage-7] Fetching key "mango" at 21:44:40.787 (should be expired) [stage-7] $ redis-cli GET mango [stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\nmango\r\n" [stage-7] Received bytes: "$-1\r\n" diff --git a/internal/test_helpers/fixtures/streams/pass b/internal/test_helpers/fixtures/streams/pass index d3de1ab..1da8456 100644 --- a/internal/test_helpers/fixtures/streams/pass +++ b/internal/test_helpers/fixtures/streams/pass @@ -215,7 +215,7 @@ Debug = true [stage-36] Running tests for Stage #36: streams-xadd-full-autoid [stage-36] $ ./spawn_redis_server.sh [stage-36] $ redis-cli xadd "mango" * foo bar -[stage-36] Received response: ""1715356868787-0"" +[stage-36] Received response: ""1715357709920-0"" [stage-36] The first part of the ID is a valid unix milliseconds timestamp [stage-36] The second part of the ID is a valid sequence number [stage-36] Test passed. @@ -293,11 +293,11 @@ Debug = true [stage-31] Received "OK" [stage-31] replica-1: $ redis-cli PSYNC ? -1 [stage-31] replica-1: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-31] replica-1: Received bytes: "+FULLRESYNC 79f0d7f2eaf9ce2e10f5165372569f313f2c4a1f 0\r\n" -[stage-31] replica-1: Received RESP value: "FULLRESYNC 79f0d7f2eaf9ce2e10f5165372569f313f2c4a1f 0" -[stage-31] Received "FULLRESYNC 79f0d7f2eaf9ce2e10f5165372569f313f2c4a1f 0" +[stage-31] replica-1: Received bytes: "+FULLRESYNC 11056bcfc27364d9b3d58eab15f912f041cb6ed6 0\r\n" +[stage-31] replica-1: Received RESP value: "FULLRESYNC 11056bcfc27364d9b3d58eab15f912f041cb6ed6 0" +[stage-31] Received "FULLRESYNC 11056bcfc27364d9b3d58eab15f912f041cb6ed6 0" [stage-31] Reading RDB file... -[stage-31] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc5D>f\xfa\bused-mem\xc2\xf0\r\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(79f0d7f2eaf9ce2e10f5165372569f313f2c4a1f\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffV\xd8B\x8a\xef\xfb\xc5\x12" +[stage-31] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\x0eH>f\xfa\bused-mem\xc2\xf0\r\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(11056bcfc27364d9b3d58eab15f912f041cb6ed6\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x12\xb2\xd8z\xc1\xbe\xe5?" [stage-31] Received RDB file [stage-31] Creating replica: 2 [stage-31] replica-2: $ redis-cli PING @@ -317,11 +317,11 @@ Debug = true [stage-31] Received "OK" [stage-31] replica-2: $ redis-cli PSYNC ? -1 [stage-31] replica-2: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-31] replica-2: Received bytes: "+FULLRESYNC 79f0d7f2eaf9ce2e10f5165372569f313f2c4a1f 0\r\n" -[stage-31] replica-2: Received RESP value: "FULLRESYNC 79f0d7f2eaf9ce2e10f5165372569f313f2c4a1f 0" -[stage-31] Received "FULLRESYNC 79f0d7f2eaf9ce2e10f5165372569f313f2c4a1f 0" +[stage-31] replica-2: Received bytes: "+FULLRESYNC 11056bcfc27364d9b3d58eab15f912f041cb6ed6 0\r\n" +[stage-31] replica-2: Received RESP value: "FULLRESYNC 11056bcfc27364d9b3d58eab15f912f041cb6ed6 0" +[stage-31] Received "FULLRESYNC 11056bcfc27364d9b3d58eab15f912f041cb6ed6 0" [stage-31] Reading RDB file... -[stage-31] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc5D>f\xfa\bused-mem\u0080\xf5\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(79f0d7f2eaf9ce2e10f5165372569f313f2c4a1f\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffdr9\xfc\xbe\x10~/" +[stage-31] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\x0eH>f\xfa\bused-mem\u0080\xf5\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(11056bcfc27364d9b3d58eab15f912f041cb6ed6\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff \x18\xa3\f\x90U^\x02" [stage-31] Received RDB file [stage-31] Creating replica: 3 [stage-31] replica-3: $ redis-cli PING @@ -341,11 +341,11 @@ Debug = true [stage-31] Received "OK" [stage-31] replica-3: $ redis-cli PSYNC ? -1 [stage-31] replica-3: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-31] replica-3: Received bytes: "+FULLRESYNC 79f0d7f2eaf9ce2e10f5165372569f313f2c4a1f 0\r\n" -[stage-31] replica-3: Received RESP value: "FULLRESYNC 79f0d7f2eaf9ce2e10f5165372569f313f2c4a1f 0" -[stage-31] Received "FULLRESYNC 79f0d7f2eaf9ce2e10f5165372569f313f2c4a1f 0" +[stage-31] replica-3: Received bytes: "+FULLRESYNC 11056bcfc27364d9b3d58eab15f912f041cb6ed6 0\r\n" +[stage-31] replica-3: Received RESP value: "FULLRESYNC 11056bcfc27364d9b3d58eab15f912f041cb6ed6 0" +[stage-31] Received "FULLRESYNC 11056bcfc27364d9b3d58eab15f912f041cb6ed6 0" [stage-31] Reading RDB file... -[stage-31] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc5D>f\xfa\bused-mem\u0080@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(79f0d7f2eaf9ce2e10f5165372569f313f2c4a1f\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\\U\xa1\xb4W\xdf\xe9\x01" +[stage-31] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\x0eH>f\xfa\bused-mem\u0080@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(11056bcfc27364d9b3d58eab15f912f041cb6ed6\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x18?;Dy\x9a\xc9," [stage-31] Received RDB file [stage-31] client: $ redis-cli SET foo 123 [stage-31] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" @@ -438,7 +438,7 @@ Debug = true [stage-31] replica-3: Not sending ACK to Master [stage-31] client: Received bytes: ":2\r\n" [stage-31] client: Received RESP value: 2 -[stage-31] WAIT command returned after 2103 ms +[stage-31] WAIT command returned after 2109 ms [stage-31] Test passed. [stage-31] Terminating program [stage-31] Program terminated successfully @@ -464,11 +464,11 @@ Debug = true [stage-30] Received "OK" [stage-30] replica-1: $ redis-cli PSYNC ? -1 [stage-30] replica-1: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-30] replica-1: Received bytes: "+FULLRESYNC 3cf3dd786973854900a38edee2284e71eeb1e72d 0\r\n" -[stage-30] replica-1: Received RESP value: "FULLRESYNC 3cf3dd786973854900a38edee2284e71eeb1e72d 0" -[stage-30] Received "FULLRESYNC 3cf3dd786973854900a38edee2284e71eeb1e72d 0" +[stage-30] replica-1: Received bytes: "+FULLRESYNC 950a7b1619b365c1b82aa2a0667ef230024d04d4 0\r\n" +[stage-30] replica-1: Received RESP value: "FULLRESYNC 950a7b1619b365c1b82aa2a0667ef230024d04d4 0" +[stage-30] Received "FULLRESYNC 950a7b1619b365c1b82aa2a0667ef230024d04d4 0" [stage-30] Reading RDB file... -[stage-30] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc7D>f\xfa\bused-mem\xc20\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(3cf3dd786973854900a38edee2284e71eeb1e72d\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xe4\x0e4\xac\x00\x1dF\xe6" +[stage-30] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\x11H>f\xfa\bused-mem\xc20\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(950a7b1619b365c1b82aa2a0667ef230024d04d4\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffe+\xb5\xf2#\xad\xf6@" [stage-30] Received RDB file [stage-30] Creating replica: 2 [stage-30] replica-2: $ redis-cli PING @@ -488,11 +488,11 @@ Debug = true [stage-30] Received "OK" [stage-30] replica-2: $ redis-cli PSYNC ? -1 [stage-30] replica-2: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-30] replica-2: Received bytes: "+FULLRESYNC 3cf3dd786973854900a38edee2284e71eeb1e72d 0\r\n" -[stage-30] replica-2: Received RESP value: "FULLRESYNC 3cf3dd786973854900a38edee2284e71eeb1e72d 0" -[stage-30] Received "FULLRESYNC 3cf3dd786973854900a38edee2284e71eeb1e72d 0" +[stage-30] replica-2: Received bytes: "+FULLRESYNC 950a7b1619b365c1b82aa2a0667ef230024d04d4 0\r\n" +[stage-30] replica-2: Received RESP value: "FULLRESYNC 950a7b1619b365c1b82aa2a0667ef230024d04d4 0" +[stage-30] Received "FULLRESYNC 950a7b1619b365c1b82aa2a0667ef230024d04d4 0" [stage-30] Reading RDB file... -[stage-30] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc8D>f\xfa\bused-mem\xc2\xc0\xf5\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(3cf3dd786973854900a38edee2284e71eeb1e72d\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x820\xb0֎\xb3\xf8\x17" +[stage-30] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\x11H>f\xfa\bused-mem\xc2\xc0\xf5\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(950a7b1619b365c1b82aa2a0667ef230024d04d4\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xcc>\"\xf5\xdb\x008\xf5" [stage-30] Received RDB file [stage-30] Creating replica: 3 [stage-30] replica-3: $ redis-cli PING @@ -512,11 +512,11 @@ Debug = true [stage-30] Received "OK" [stage-30] replica-3: $ redis-cli PSYNC ? -1 [stage-30] replica-3: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-30] replica-3: Received bytes: "+FULLRESYNC 3cf3dd786973854900a38edee2284e71eeb1e72d 0\r\n" -[stage-30] replica-3: Received RESP value: "FULLRESYNC 3cf3dd786973854900a38edee2284e71eeb1e72d 0" -[stage-30] Received "FULLRESYNC 3cf3dd786973854900a38edee2284e71eeb1e72d 0" +[stage-30] replica-3: Received bytes: "+FULLRESYNC 950a7b1619b365c1b82aa2a0667ef230024d04d4 0\r\n" +[stage-30] replica-3: Received RESP value: "FULLRESYNC 950a7b1619b365c1b82aa2a0667ef230024d04d4 0" +[stage-30] Received "FULLRESYNC 950a7b1619b365c1b82aa2a0667ef230024d04d4 0" [stage-30] Reading RDB file... -[stage-30] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc8D>f\xfa\bused-mem\xc2\xc0@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(3cf3dd786973854900a38edee2284e71eeb1e72d\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xba\x17(\x9eg|o9" +[stage-30] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\x11H>f\xfa\bused-mem\xc2\xc0@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(950a7b1619b365c1b82aa2a0667ef230024d04d4\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xf4\x19\xba\xbd2ϯ\xdb" [stage-30] Received RDB file [stage-30] client: $ redis-cli WAIT 3 500 [stage-30] client: Sent bytes: "*3\r\n$4\r\nWAIT\r\n$1\r\n3\r\n$3\r\n500\r\n" @@ -550,7 +550,7 @@ Debug = true [stage-28] Running tests for Stage #28: repl-replica-getack-nonzero [stage-28] Master is running on port 6379 -[stage-28] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-28] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-28] master: Waiting for replica to initiate handshake with "PING" command [stage-28] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-28] master: Received RESP value: ["PING"] @@ -605,7 +605,7 @@ Debug = true [stage-27] Running tests for Stage #27: repl-replica-getack [stage-27] Master is running on port 6379 -[stage-27] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-27] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-27] master: Waiting for replica to initiate handshake with "PING" command [stage-27] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-27] master: Received RESP value: ["PING"] @@ -644,7 +644,7 @@ Debug = true [stage-26] Running tests for Stage #26: repl-cmd-processing [stage-26] Master is running on port 6379 -[stage-26] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-26] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-26] master: Waiting for replica to initiate handshake with "PING" command [stage-26] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-26] master: Received RESP value: ["PING"] @@ -720,11 +720,11 @@ Debug = true [stage-25] Received "OK" [stage-25] replica-1: $ redis-cli PSYNC ? -1 [stage-25] replica-1: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-25] replica-1: Received bytes: "+FULLRESYNC e76651dc8a609d0cf9cd29b9a9c7da223a2016bc 0\r\n" -[stage-25] replica-1: Received RESP value: "FULLRESYNC e76651dc8a609d0cf9cd29b9a9c7da223a2016bc 0" -[stage-25] Received "FULLRESYNC e76651dc8a609d0cf9cd29b9a9c7da223a2016bc 0" +[stage-25] replica-1: Received bytes: "+FULLRESYNC bd1d01cbfc7489ee5f189495d5313379d448267d 0\r\n" +[stage-25] replica-1: Received RESP value: "FULLRESYNC bd1d01cbfc7489ee5f189495d5313379d448267d 0" +[stage-25] Received "FULLRESYNC bd1d01cbfc7489ee5f189495d5313379d448267d 0" [stage-25] Reading RDB file... -[stage-25] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc9D>f\xfa\bused-mem\u0080S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(e76651dc8a609d0cf9cd29b9a9c7da223a2016bc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x88'hY@\x9e\xa4/" +[stage-25] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\x13H>f\xfa\bused-mem\xc2`S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(bd1d01cbfc7489ee5f189495d5313379d448267d\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xd4\x06\x10gex\xffB" [stage-25] Received RDB file [stage-25] Creating replica: 2 [stage-25] replica-2: $ redis-cli PING @@ -744,11 +744,11 @@ Debug = true [stage-25] Received "OK" [stage-25] replica-2: $ redis-cli PSYNC ? -1 [stage-25] replica-2: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-25] replica-2: Received bytes: "+FULLRESYNC e76651dc8a609d0cf9cd29b9a9c7da223a2016bc 0\r\n" -[stage-25] replica-2: Received RESP value: "FULLRESYNC e76651dc8a609d0cf9cd29b9a9c7da223a2016bc 0" -[stage-25] Received "FULLRESYNC e76651dc8a609d0cf9cd29b9a9c7da223a2016bc 0" +[stage-25] replica-2: Received bytes: "+FULLRESYNC bd1d01cbfc7489ee5f189495d5313379d448267d 0\r\n" +[stage-25] replica-2: Received RESP value: "FULLRESYNC bd1d01cbfc7489ee5f189495d5313379d448267d 0" +[stage-25] Received "FULLRESYNC bd1d01cbfc7489ee5f189495d5313379d448267d 0" [stage-25] Reading RDB file... -[stage-25] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc9D>f\xfa\bused-mem\xc2\xf0:\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(e76651dc8a609d0cf9cd29b9a9c7da223a2016bc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffu\xeaP\b\xa0h\x82$" +[stage-25] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\x13H>f\xfa\bused-mem\xc2\xd0:\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(bd1d01cbfc7489ee5f189495d5313379d448267d\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffds\xee\x97t\xf2OW" [stage-25] Received RDB file [stage-25] Creating replica: 3 [stage-25] replica-3: $ redis-cli PING @@ -768,11 +768,11 @@ Debug = true [stage-25] Received "OK" [stage-25] replica-3: $ redis-cli PSYNC ? -1 [stage-25] replica-3: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-25] replica-3: Received bytes: "+FULLRESYNC e76651dc8a609d0cf9cd29b9a9c7da223a2016bc 0\r\n" -[stage-25] replica-3: Received RESP value: "FULLRESYNC e76651dc8a609d0cf9cd29b9a9c7da223a2016bc 0" -[stage-25] Received "FULLRESYNC e76651dc8a609d0cf9cd29b9a9c7da223a2016bc 0" +[stage-25] replica-3: Received bytes: "+FULLRESYNC bd1d01cbfc7489ee5f189495d5313379d448267d 0\r\n" +[stage-25] replica-3: Received RESP value: "FULLRESYNC bd1d01cbfc7489ee5f189495d5313379d448267d 0" +[stage-25] Received "FULLRESYNC bd1d01cbfc7489ee5f189495d5313379d448267d 0" [stage-25] Reading RDB file... -[stage-25] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xcaD>f\xfa\bused-mem\xc2\x00J\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(e76651dc8a609d0cf9cd29b9a9c7da223a2016bc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff],\xa1\x12`\x7f\xb8m" +[stage-25] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\x13H>f\xfa\bused-mem\xc2\xe0I\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(bd1d01cbfc7489ee5f189495d5313379d448267d\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffAa\xbd_ݞ\x183" [stage-25] Received RDB file [stage-25] client: $ redis-cli SET foo 123 [stage-25] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" @@ -857,11 +857,11 @@ Debug = true [stage-24] Received "OK" [stage-24] replica: $ redis-cli PSYNC ? -1 [stage-24] replica: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-24] replica: Received bytes: "+FULLRESYNC 64a069c8b2a42cb4dbc84cfff265543a84a61e48 0\r\n" -[stage-24] replica: Received RESP value: "FULLRESYNC 64a069c8b2a42cb4dbc84cfff265543a84a61e48 0" -[stage-24] Received "FULLRESYNC 64a069c8b2a42cb4dbc84cfff265543a84a61e48 0" +[stage-24] replica: Received bytes: "+FULLRESYNC bc00726e14c6da6d5b42f99e1ef0366a68d885a3 0\r\n" +[stage-24] replica: Received RESP value: "FULLRESYNC bc00726e14c6da6d5b42f99e1ef0366a68d885a3 0" +[stage-24] Received "FULLRESYNC bc00726e14c6da6d5b42f99e1ef0366a68d885a3 0" [stage-24] Reading RDB file... -[stage-24] replica: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xcaD>f\xfa\bused-mem\xc2`S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(64a069c8b2a42cb4dbc84cfff265543a84a61e48\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x80\xf8\xda\xcf\xd2\xf5\x89C" +[stage-24] replica: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\x13H>f\xfa\bused-mem\xc2@S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(bc00726e14c6da6d5b42f99e1ef0366a68d885a3\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xdaE\xbb\xbf.\xe5tJ" [stage-24] Received RDB file [stage-24] client: $ redis-cli SET foo 123 [stage-24] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" @@ -916,11 +916,11 @@ Debug = true [stage-23] Received "OK" [stage-23] client: $ redis-cli PSYNC ? -1 [stage-23] client: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-23] client: Received bytes: "+FULLRESYNC 3587923c410e47bf31e925d81e75f6046bb30d46 0\r\n" -[stage-23] client: Received RESP value: "FULLRESYNC 3587923c410e47bf31e925d81e75f6046bb30d46 0" -[stage-23] Received "FULLRESYNC 3587923c410e47bf31e925d81e75f6046bb30d46 0" +[stage-23] client: Received bytes: "+FULLRESYNC 59c4dc906896fb2f1f908a89156b850e06065ef1 0\r\n" +[stage-23] client: Received RESP value: "FULLRESYNC 59c4dc906896fb2f1f908a89156b850e06065ef1 0" +[stage-23] Received "FULLRESYNC 59c4dc906896fb2f1f908a89156b850e06065ef1 0" [stage-23] Reading RDB file... -[stage-23] client: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xcaD>f\xfa\bused-mem\xc20\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(3587923c410e47bf31e925d81e75f6046bb30d46\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x82\x85\x98\x10\xd0!\xe0M" +[stage-23] client: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\x13H>f\xfa\bused-mem\xc20\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(59c4dc906896fb2f1f908a89156b850e06065ef1\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xf5a:\x8dz&n\x19" [stage-23] Received RDB file [stage-23] Test passed. [stage-23] Terminating program @@ -945,9 +945,9 @@ Debug = true [stage-22] Received "OK" [stage-22] client: $ redis-cli PSYNC ? -1 [stage-22] client: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-22] client: Received bytes: "+FULLRESYNC c51e35c4900b53a64da599e31ed0f2e135827e79 0\r\n" -[stage-22] client: Received RESP value: "FULLRESYNC c51e35c4900b53a64da599e31ed0f2e135827e79 0" -[stage-22] Received "FULLRESYNC c51e35c4900b53a64da599e31ed0f2e135827e79 0" +[stage-22] client: Received bytes: "+FULLRESYNC 9932ecf2f66b217fed8c947627dfb931b67d8857 0\r\n" +[stage-22] client: Received RESP value: "FULLRESYNC 9932ecf2f66b217fed8c947627dfb931b67d8857 0" +[stage-22] Received "FULLRESYNC 9932ecf2f66b217fed8c947627dfb931b67d8857 0" [stage-22] Test passed. [stage-22] Terminating program [stage-22] Program terminated successfully @@ -975,7 +975,7 @@ Debug = true [stage-20] Running tests for Stage #20: repl-replica-psync [stage-20] Master is running on port 6379 -[stage-20] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-20] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-20] master: Waiting for replica to initiate handshake with "PING" command [stage-20] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-20] master: Received RESP value: ["PING"] @@ -1006,7 +1006,7 @@ Debug = true [stage-19] Running tests for Stage #19: repl-replica-replconf [stage-19] Master is running on port 6379 -[stage-19] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-19] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-19] master: Waiting for replica to initiate handshake with "PING" command [stage-19] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-19] master: Received RESP value: ["PING"] @@ -1031,7 +1031,7 @@ Debug = true [stage-18] Running tests for Stage #18: repl-replica-ping [stage-18] Master is running on port 6379. -[stage-18] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-18] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-18] master: Waiting for replica to initiate handshake with "PING" command [stage-18] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-18] master: Received RESP value: ["PING"] @@ -1046,9 +1046,9 @@ Debug = true [stage-17] $ ./spawn_redis_server.sh [stage-17] client: $ redis-cli INFO replication [stage-17] client: Sent bytes: "*2\r\n$4\r\nINFO\r\n$11\r\nreplication\r\n" -[stage-17] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:35c509d64c1974499b177be6feeb7076105b42c3\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" -[stage-17] client: Received RESP value: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:35c509d64c1974499b177be6feeb7076105b42c3\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" -[stage-17] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:35c509d64c1974499b177be6feeb7076105b42c3\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-17] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:fce177b51f2533035c89ecbcdf9eda0dd50d9ff7\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" +[stage-17] client: Received RESP value: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:fce177b51f2533035c89ecbcdf9eda0dd50d9ff7\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-17] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:fce177b51f2533035c89ecbcdf9eda0dd50d9ff7\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" [stage-17] Found master_replid:xxx in response. [stage-17] Found master_reploffset:0 in response. [stage-17] Test passed. @@ -1057,7 +1057,7 @@ Debug = true [stage-16] Running tests for Stage #16: repl-info-replica [stage-16] Master is running on port 6379 -[stage-16] $ ./spawn_redis_server.sh --port 6380 --replicaof localhost 6379 +[stage-16] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" [stage-16] master: Received bytes: "*1\r\n$4\r\nPING\r\n" [stage-16] master: Received RESP value: ["PING"] [stage-16] master: Sent "PONG" @@ -1089,9 +1089,9 @@ Debug = true [stage-15] $ ./spawn_redis_server.sh [stage-15] client: $ redis-cli INFO replication [stage-15] client: Sent bytes: "*2\r\n$4\r\nINFO\r\n$11\r\nreplication\r\n" -[stage-15] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:e12adefd83b2283982b314f8082e942360744ae9\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" -[stage-15] client: Received RESP value: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:e12adefd83b2283982b314f8082e942360744ae9\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" -[stage-15] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:e12adefd83b2283982b314f8082e942360744ae9\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-15] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:49ed32bd7431f5109bcd016260fc88187559a447\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" +[stage-15] client: Received RESP value: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:49ed32bd7431f5109bcd016260fc88187559a447\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-15] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:49ed32bd7431f5109bcd016260fc88187559a447\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" [stage-15] Found role:master in response. [stage-15] Test passed. [stage-15] Terminating program @@ -1106,7 +1106,7 @@ Debug = true [stage-14] Program terminated successfully [stage-13] Running tests for Stage #13: rdb-read-value-with-expiry -[stage-13] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3916749387 --dbfilename banana.rdb +[stage-13] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3219304145 --dbfilename banana.rdb [stage-13] client: $ redis-cli GET blueberry [stage-13] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$9\r\nblueberry\r\n" [stage-13] client: Received bytes: "$4\r\npear\r\n" @@ -1133,7 +1133,7 @@ Debug = true [stage-12] Running tests for Stage #12: rdb-read-multiple-string-values [stage-12] Created RDB file with key-value pairs: "pineapple"="pear", "raspberry"="strawberry", "pear"="pineapple" -[stage-12] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1159885408 --dbfilename strawberry.rdb +[stage-12] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles445392019 --dbfilename strawberry.rdb [stage-12] client: $ redis-cli GET pineapple [stage-12] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$9\r\npineapple\r\n" [stage-12] client: Received bytes: "$4\r\npear\r\n" @@ -1155,19 +1155,19 @@ Debug = true [stage-11] Running tests for Stage #11: rdb-read-multiple-keys [stage-11] Created RDB file with 4 keys: ["mango" "pineapple" "blueberry" "apple"] -[stage-11] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3925017577 --dbfilename strawberry.rdb +[stage-11] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1604981223 --dbfilename strawberry.rdb [stage-11] client: $ redis-cli KEYS * [stage-11] client: Sent bytes: "*2\r\n$4\r\nKEYS\r\n$1\r\n*\r\n" -[stage-11] client: Received bytes: "*4\r\n$5\r\nmango\r\n$5\r\napple\r\n$9\r\npineapple\r\n$9\r\nblueberry\r\n" -[stage-11] client: Received RESP value: ["mango", "apple", "pineapple", "blueberry"] -[stage-11] Received ["mango", "apple", "pineapple", "blueberry"] +[stage-11] client: Received bytes: "*4\r\n$5\r\napple\r\n$9\r\nblueberry\r\n$9\r\npineapple\r\n$5\r\nmango\r\n" +[stage-11] client: Received RESP value: ["apple", "blueberry", "pineapple", "mango"] +[stage-11] Received ["apple", "blueberry", "pineapple", "mango"] [stage-11] Test passed. [stage-11] Terminating program [stage-11] Program terminated successfully [stage-10] Running tests for Stage #10: rdb-read-string-value [stage-10] Created RDB file with single key-value pair: grape="raspberry" -[stage-10] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1025445431 --dbfilename blueberry.rdb +[stage-10] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3599055013 --dbfilename blueberry.rdb [stage-10] client: $ redis-cli GET grape [stage-10] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\ngrape\r\n" [stage-10] client: Received bytes: "$9\r\nraspberry\r\n" @@ -1179,7 +1179,7 @@ Debug = true [stage-9] Running tests for Stage #9: rdb-read-key [stage-9] Created RDB file with single key: "orange" -[stage-9] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2179357849 --dbfilename mango.rdb +[stage-9] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3123330290 --dbfilename mango.rdb [stage-9] client: $ redis-cli KEYS * [stage-9] client: Sent bytes: "*2\r\n$4\r\nKEYS\r\n$1\r\n*\r\n" [stage-9] client: Received bytes: "*1\r\n$6\r\norange\r\n" @@ -1190,12 +1190,12 @@ Debug = true [stage-9] Program terminated successfully [stage-8] Running tests for Stage #8: rdb-config -[stage-8] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles4038935 --dbfilename raspberry.rdb +[stage-8] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles380550116 --dbfilename raspberry.rdb [stage-8] client: $ redis-cli CONFIG GET dir [stage-8] client: Sent bytes: "*3\r\n$6\r\nCONFIG\r\n$3\r\nGET\r\n$3\r\ndir\r\n" -[stage-8] client: Received bytes: "*2\r\n$3\r\ndir\r\n$72\r\n/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles4038935\r\n" -[stage-8] client: Received RESP value: ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles4038935"] -[stage-8] Received ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles4038935"] +[stage-8] client: Received bytes: "*2\r\n$3\r\ndir\r\n$74\r\n/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles380550116\r\n" +[stage-8] client: Received RESP value: ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles380550116"] +[stage-8] Received ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles380550116"] [stage-8] Test passed. [stage-8] Terminating program [stage-8] Program terminated successfully @@ -1207,15 +1207,15 @@ Debug = true [stage-7] Received bytes: "+OK\r\n" [stage-7] Received RESP value: "OK" [stage-7] Received "OK" -[stage-7] Received OK at 21:31:17.928 -[stage-7] Fetching key "banana" at 21:31:17.928 (should not be expired) +[stage-7] Received OK at 21:45:19.116 +[stage-7] Fetching key "banana" at 21:45:19.116 (should not be expired) [stage-7] $ redis-cli GET banana [stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$6\r\nbanana\r\n" [stage-7] Received bytes: "$6\r\norange\r\n" [stage-7] Received RESP value: "orange" [stage-7] Received "orange" [stage-7] Sleeping for 101ms -[stage-7] Fetching key "banana" at 21:31:18.031 (should be expired) +[stage-7] Fetching key "banana" at 21:45:19.220 (should be expired) [stage-7] $ redis-cli GET banana [stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$6\r\nbanana\r\n" [stage-7] Received bytes: "$-1\r\n" diff --git a/internal/test_repl_info_replica.go b/internal/test_repl_info_replica.go index 8d2017a..f556a41 100644 --- a/internal/test_repl_info_replica.go +++ b/internal/test_repl_info_replica.go @@ -30,7 +30,7 @@ func testReplInfoReplica(stageHarness *test_case_harness.TestCaseHarness) error replica := redis_executable.NewRedisExecutable(stageHarness) if err := replica.Run("--port", "6380", - "--replicaof", "localhost", "6379"); err != nil { + "--replicaof", "localhost 6379"); err != nil { return err } diff --git a/internal/test_repl_replica_cmd_processing.go b/internal/test_repl_replica_cmd_processing.go index 210a1fd..f702402 100644 --- a/internal/test_repl_replica_cmd_processing.go +++ b/internal/test_repl_replica_cmd_processing.go @@ -29,7 +29,7 @@ func testReplCmdProcessing(stageHarness *test_case_harness.TestCaseHarness) erro replica := redis_executable.NewRedisExecutable(stageHarness) if err := replica.Run("--port", "6380", - "--replicaof", "localhost", "6379"); err != nil { + "--replicaof", "localhost 6379"); err != nil { return err } diff --git a/internal/test_repl_replica_getack_nonzero.go b/internal/test_repl_replica_getack_nonzero.go index d7d07bd..bc07e97 100644 --- a/internal/test_repl_replica_getack_nonzero.go +++ b/internal/test_repl_replica_getack_nonzero.go @@ -28,7 +28,7 @@ func testReplGetaAckNonZero(stageHarness *test_case_harness.TestCaseHarness) err replica := redis_executable.NewRedisExecutable(stageHarness) if err := replica.Run("--port", "6380", - "--replicaof", "localhost", "6379"); err != nil { + "--replicaof", "localhost 6379"); err != nil { return err } diff --git a/internal/test_repl_replica_getack_zero.go b/internal/test_repl_replica_getack_zero.go index bb11c1d..b00edd6 100644 --- a/internal/test_repl_replica_getack_zero.go +++ b/internal/test_repl_replica_getack_zero.go @@ -27,7 +27,7 @@ func testReplGetaAckZero(stageHarness *test_case_harness.TestCaseHarness) error replica := redis_executable.NewRedisExecutable(stageHarness) if err := replica.Run("--port", "6380", - "--replicaof", "localhost", "6379"); err != nil { + "--replicaof", "localhost 6379"); err != nil { return err } diff --git a/internal/test_repl_replica_ping.go b/internal/test_repl_replica_ping.go index 30dadd2..33f1622 100644 --- a/internal/test_repl_replica_ping.go +++ b/internal/test_repl_replica_ping.go @@ -25,7 +25,7 @@ func testReplReplicaSendsPing(stageHarness *test_case_harness.TestCaseHarness) e replica := redis_executable.NewRedisExecutable(stageHarness) if err := replica.Run("--port", "6380", - "--replicaof", "localhost", "6379"); err != nil { + "--replicaof", "localhost 6379"); err != nil { return err } diff --git a/internal/test_repl_replica_psync.go b/internal/test_repl_replica_psync.go index 7cb95af..c543e44 100644 --- a/internal/test_repl_replica_psync.go +++ b/internal/test_repl_replica_psync.go @@ -27,7 +27,7 @@ func testReplReplicaSendsPsync(stageHarness *test_case_harness.TestCaseHarness) replica := redis_executable.NewRedisExecutable(stageHarness) if err := replica.Run("--port", "6380", - "--replicaof", "localhost", "6379"); err != nil { + "--replicaof", "localhost 6379"); err != nil { return err } diff --git a/internal/test_repl_replica_replconf.go b/internal/test_repl_replica_replconf.go index f6ebfcd..a406fe0 100644 --- a/internal/test_repl_replica_replconf.go +++ b/internal/test_repl_replica_replconf.go @@ -25,7 +25,7 @@ func testReplReplicaSendsReplconf(stageHarness *test_case_harness.TestCaseHarnes replica := redis_executable.NewRedisExecutable(stageHarness) if err := replica.Run("--port", "6380", - "--replicaof", "localhost", "6379"); err != nil { + "--replicaof", "localhost 6379"); err != nil { return err }