Stuck on Redis Stage #LA7 in Rust

I’m stuck on Stage 6.

I have successfully implemented the SET and GET commands locally and can use them with the official resdis cli, but the tests are failing. I had no issues with the Python version.

Here are my logs:

[stage-6] Running tests for Stage #6: Implement the SET & GET commands
[stage-6] $ ./spawn_redis_server.sh
[your_program] Logs from your program will appear here!
[stage-6] Setting key apple to mango
[stage-6] $ redis-cli SET apple mango
[stage-6] Sent bytes: "*3\r\n$3\r\nSET\r\n$5\r\napple\r\n$5\r\nmango\r\n"
[stage-6] Received bytes: "+OK\r\n"
[stage-6] Received RESP value: "OK"
[your_program] accepted new connection
[your_program] handling connection
[your_program] received value: Array([BulkString(Some("SET")), BulkString(Some("apple")), BulkString(Some("mango"))])
[your_program] args [BulkString(Some("apple")), BulkString(Some("mango"))]
[your_program] Sending value SimpleString("OK")
[stage-6] Received "OK"
[stage-6] Getting key apple
[stage-6] $ redis-cli GET apple
[stage-6] Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\napple\r\n"
[stage-6] Received bytes: "+OK\r\n"
[stage-6] Received RESP value: "OK"
[stage-6] Expected "mango", got "OK"
[stage-6] Test failed
[stage-6] Terminating program
[your_program] received value: Array([BulkString(Some("SET")), BulkString(Some("apple")), BulkString(Some("mango"))])
[your_program] args [BulkString(Some("apple")), BulkString(Some("mango"))]
[your_program] Sending value SimpleString("OK")
[stage-6] Program terminated successfully

The logs of the test show that a get command is set, but my application gets another set command that is identical to the previous set command.

[07:15:25] 🐟 hwm@zebra in [Python 3.11.8] via 🦀 v1.75.0 on  master [!] ~/myspace/codecrafters-redis-rust 
❯ redis-cli set foo bar
OK

[07:15:44] 🐟 hwm@zebra in [Python 3.11.8] via 🦀 v1.75.0 on  master [!] ~/myspace/codecrafters-redis-rust 
❯ redis-cli get foo
"bar"

And the application logs for the manual test.

Logs from your program will appear here!
accepted new connection
handling connection
received value: Array([BulkString(Some("set")), BulkString(Some("foo")), BulkString(Some("bar"))])
args [BulkString(Some("foo")), BulkString(Some("bar"))]
Sending value SimpleString("OK")
accepted new connection
handling connection
received value: Array([BulkString(Some("get")), BulkString(Some("foo"))])
get args [BulkString(Some("foo"))]
Sending value BulkString(Some("bar"))

And here’s a snippet of my code:

    println!("handling connection");
    loop {
        let value = response_handler.read_value().await.unwrap();
        let response = if let Some(value) = value {
            println!("received value: {:?}", value);
            // println!("received value ser: {}", value.serialize());
            let (command, args) = extract_command(value).unwrap();

            match command.to_lowercase().as_str() {
                "ping" => Value::SimpleString("PONG".to_string()),

                "echo" => args.first().unwrap().clone(),

                "set" => run_set_command(args).await,
                "get" => run_get_command(args).await,

                c => panic!("Cannot handle command {}", c),
            }
        } else {
            break;
        };

        println!("Sending value {:?}", response);

        response_handler.write_value(response).await.unwrap();
    }

I have no idea why I have a different behaviour in the test and locally and what else I can try

@hwmrocker is it possible that you aren’t clear a buffer after reading the first command? That could explain why the same command is returned when you read again.

Hard to tell is that’s the case without seeing what response_handler is and how read_value() is implemented.

The reason this is different from the local test listed above could be that SET key value and GET key are sent on the same connection, not different connections.

2 Likes

Ah, that is a good point. This could be the reason.

1 Like

The issue was that I didn’t advance the input buffer after the command. I could replicate this locally with

echo -e "set foo bar\nget foo" | redis-cli
2 Likes

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.

Note: I’ve updated the title of this post to include the stage ID (#LA7). You can learn about the stages rename here: Upcoming change: Stages overhaul.