Skip to content

Commit fa85c8e

Browse files
authored
Merge pull request codecrafters-io#225 from codecrafters-io/add-transactions-docs
Add support for queuing commands within a transaction
2 parents 047d18e + 8d1beb4 commit fa85c8e

File tree

1 file changed

+151
-30
lines changed

1 file changed

+151
-30
lines changed

course-definition.yml

+151-30
Original file line numberDiff line numberDiff line change
@@ -3458,7 +3458,32 @@ stages:
34583458
name: "Queueing commands"
34593459
difficulty: medium
34603460
description_md: |
3461-
**🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below.
3461+
In this stage, you'll add support for queuing commands within a transaction.
3462+
3463+
### Queuing commands
3464+
3465+
After [MULTI](https://redis.io/docs/latest/commands/multi/) is executed, any further commands
3466+
from a connection are queued until [EXEC](https://redis.io/docs/latest/commands/exec/) is executed.
3467+
3468+
The response to all of these commands is `+QUEUED\r\n` (That's `QUEUED` encoded as a [Simple String](https://redis.io/docs/latest/develop/reference/protocol-spec/#simple-strings)).
3469+
3470+
Example:
3471+
3472+
```bash
3473+
$ redis-cli
3474+
> MULTI
3475+
OK
3476+
> SET foo 41
3477+
QUEUED
3478+
> INCR foo
3479+
QUEUED
3480+
3481+
... (and so on, until EXEC is executed)
3482+
```
3483+
3484+
When commands are queued, they should not be executed or alter the database in any way.
3485+
3486+
In the example above, until `EXEC` is executed, the key `foo` will not exist.
34623487
34633488
### Tests
34643489
@@ -3471,17 +3496,18 @@ stages:
34713496
The tester will then connect to your server as a Redis client, and send multiple commands using the same connection:
34723497
34733498
```bash
3474-
$ redis-cli MULTI
3475-
> SET foo 41
3476-
> INCR foo
3499+
$ redis-cli
3500+
> MULTI
3501+
> SET foo 41 (expecting "+QUEUED\r\n")
3502+
> INCR foo (expecting "+QUEUED\r\n")
34773503
```
34783504
3479-
The tester will then create another connection to your master as a Redis client, and send a single command:
3505+
Since these commands were only "queued", the key `foo` should not exist yet. The tester will verify this by creating
3506+
another connection and sending this command:
34803507
34813508
```bash
3482-
$ redis-cli GET foo
3509+
$ redis-cli GET foo (expecting `$-1\r\n` as the response)
34833510
```
3484-
34853511
marketing_md: |
34863512
In this stage, you'll implement queueing commands to a transaction.
34873513
@@ -3490,7 +3516,31 @@ stages:
34903516
name: "Executing a transaction"
34913517
difficulty: hard
34923518
description_md: |
3493-
**🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below.
3519+
In this stage, you'll add support for executing a transaction that contains multiple commands.
3520+
3521+
### Executing a transaction
3522+
3523+
When the [EXEC](https://redis.io/docs/latest/commands/exec/) command is sent within a transaction,
3524+
all commands queued in that transaction are executed.
3525+
3526+
The response to [EXEC](https://redis.io/docs/latest/commands/exec/) is an array of the responses of the queued commands.
3527+
3528+
Example:
3529+
3530+
```bash
3531+
$ redis-cli
3532+
> MULTI
3533+
OK
3534+
> SET foo 41
3535+
QUEUED
3536+
> INCR foo
3537+
QUEUED
3538+
> EXEC
3539+
1) OK
3540+
2) (integer) 42
3541+
```
3542+
3543+
In the above example, `OK` is the response of the `SET` command, and `42` is the response of the `INCR` command.
34943544
34953545
### Tests
34963546
@@ -3504,19 +3554,20 @@ stages:
35043554
35053555
```bash
35063556
$ redis-cli MULTI
3507-
> SET foo 6
3508-
> INCR foo
3509-
> INCR bar
3510-
> GET bar
3511-
> EXEC
3557+
> SET foo 6 (expecting "+QUEUED\r\n")
3558+
> INCR foo (expecting "+QUEUED\r\n")
3559+
> INCR bar (expecting "+QUEUED\r\n")
3560+
> GET bar (expecting "+QUEUED\r\n")
3561+
> EXEC (expecting an array of responses for the queued commands)
35123562
```
35133563
3514-
The tester will then create another connection to your server as a Redis client, and send a single command:
3564+
Since the transaction was executed, the key `foo` should exist and have the value `7`.
3565+
3566+
The tester will verify this by running a GET command:
35153567
35163568
```bash
3517-
$ redis-cli GET foo
3569+
$ redis-cli GET foo (expecting "7" encoded as a bulk string)
35183570
```
3519-
35203571
marketing_md: |
35213572
In this stage, you'll implement executing a successful transaction.
35223573
@@ -3525,7 +3576,30 @@ stages:
35253576
name: "The DISCARD command"
35263577
difficulty: easy
35273578
description_md: |
3528-
**🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below.
3579+
In this stage, you'll add support for the DISCARD command.
3580+
3581+
### The DISCARD command
3582+
3583+
[DISCARD](https://redis.io/docs/latest/commands/discard/) is used to abort a transactions. It discards all commands queued in a transaction,
3584+
and returns `+OK\r\n`.
3585+
3586+
Example:
3587+
3588+
```bash
3589+
$ redis-cli
3590+
> MULTI
3591+
OK
3592+
> SET foo 41
3593+
QUEUED
3594+
> DISCARD
3595+
OK
3596+
> DISCARD
3597+
(error) ERR DISCARD without MULTI
3598+
```
3599+
3600+
In the above example, note that the first `DISCARD` returns `OK`, but the second `DISCARD` returns an error since the transaction was aborted.
3601+
3602+
### DISCARD
35293603
35303604
### Tests
35313605
@@ -3538,13 +3612,13 @@ stages:
35383612
The tester will then connect to your server as a Redis client, and send multiple commands using the same connection:
35393613
35403614
```bash
3541-
$ redis-cli MULTI
3542-
> SET foo 41
3543-
> INCR foo
3544-
> DISCARD
3545-
> GET foo
3546-
> GET bar
3547-
> DISCARD
3615+
$ redis-cli
3616+
> MULTI
3617+
> SET foo 41 (expecting "+QUEUED\r\n")
3618+
> INCR foo (expecting "+QUEUED\r\n")
3619+
> DISCARD (expecting "+OK\r\n")
3620+
> GET foo (expecting "$-1\r\n" as the response)
3621+
> DISCARD (expecting "-ERR DISCARD without MULTI\r\n" as the response)
35483622
```
35493623
35503624
marketing_md: |
@@ -3555,7 +3629,34 @@ stages:
35553629
name: "Failures within transactions"
35563630
difficulty: medium
35573631
description_md: |
3558-
**🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below.
3632+
In this stage, you'll add support for handling failures within a transaction.
3633+
3634+
### Failures within transactions
3635+
3636+
When executing a transaction, if a command fails, the error is captured and returned within the response for `EXEC`. All other commands in
3637+
the transaction are still executed.
3638+
3639+
You can read more about this behaviour [in the official Redis docs](https://redis.io/docs/latest/develop/interact/transactions/#errors-inside-a-transaction).
3640+
3641+
Example:
3642+
3643+
```bash
3644+
$ redis-cli
3645+
> MULTI
3646+
OK
3647+
> SET foo xyz
3648+
QUEUED
3649+
> INCR foo
3650+
QUEUED
3651+
> SET bar 7
3652+
> EXEC
3653+
1) OK
3654+
2) (error) ERR value is not an integer or out of range
3655+
3) OK
3656+
```
3657+
3658+
In the example above, note that the error for the `INCR` command was returned as the second array element. The third command (`SET bar 7`) was
3659+
still executed successfully.
35593660
35603661
### Tests
35613662
@@ -3568,21 +3669,41 @@ stages:
35683669
The tester will then connect to your server as a Redis client, and send multiple commands using the same connection:
35693670
35703671
```bash
3571-
$ redis-cli SET foo abc
3572-
> SET bar 7
3672+
$ redis-cli
3673+
> SET foo abc
3674+
OK
3675+
> SET bar 41
3676+
OK
35733677
> MULTI
3678+
OK
35743679
> INCR foo
3680+
QUEUED
35753681
> INCR bar
3682+
QUEUED
35763683
> EXEC
3684+
1) (error) ERR value is not an integer or out of range
3685+
2) (integer) 42
35773686
```
35783687
3579-
The tester will then create another connection to your server as a Redis client, and send a single command:
3688+
The expected response for `EXEC` is a [RESP array](https://redis.io/docs/latest/develop/reference/protocol-spec/#arrays) of
3689+
the responses of the queued commands. The exact bytes will be:
35803690
35813691
```bash
3582-
$ redis-cli GET foo
3583-
> GET bar
3692+
*2\r\n-ERR value is not an integer or out of range\r\n:42\r\n
35843693
```
35853694
3695+
The tester will also verify that the last command was successfully executed and that the key `bar` exists:
3696+
3697+
```bash
3698+
$ redis-cli
3699+
> GET foo (expecting "$3\r\nabc\r\n" as the response)
3700+
> GET bar (expecting "$2\r\n42\r\n" as the response)
3701+
```
3702+
3703+
### Notes
3704+
3705+
- There are a subset of command failures (like syntax errors) that will cause a transaction to be aborted entirely. We won't
3706+
cover those in this challenge.
35863707
marketing_md: |
35873708
In this stage, you'll implement handling failures while executing a transaction.
35883709

0 commit comments

Comments
 (0)