{
  "schema_version": 2,
  "id": "develop/clients/rust/transpipe",
  "title": "Pipelines and transactions",
  "url": "https://redis.io/docs/latest/develop/clients/rust/transpipe/",
  "summary": "Learn how to use Redis pipelines and transactions",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-09-09T11:06:34+01:00",
  "page_type": "content",
  "content_hash": "637f74f84e364c4df0f90adb2c50a6ae4a2ac703b5ad3dd01306822e366e1de9",
  "sections": [
    {
      "id": "execute-a-pipeline",
      "title": "Execute a pipeline",
      "role": "content",
      "text": "To execute commands in a pipeline, you first create a pipeline object\nand then add commands to it using methods that resemble the standard\ncommand methods (for example, `set()` and `get()`). The commands are\nbuffered in the pipeline and only execute when you call the `exec()`\nmethod on the pipeline object. If you need the results from the\ncommands, use the `query()` method, which returns\nthe results from all the commands in order.\n\nNote that the command methods for a pipeline always return the original\npipeline object, so you can \"chain\" several commands together, as the\nexample below shows:\n\nFoundational: Use pipelines to batch multiple commands together and reduce network round trips\n\n**Difficulty:** Beginner\n\n**Available in:** Rust (Synchronous)\n\n##### Rust (Synchronous)\n\n[code example]"
    },
    {
      "id": "execute-a-transaction",
      "title": "Execute a transaction",
      "role": "content",
      "text": "You can execute a simple transaction by adding the `atomic()` method to a pipeline.\n\nFoundational: Use transactions to execute multiple commands atomically without interruption from other clients\n\n**Difficulty:** Beginner\n\n**Available in:** Rust (Synchronous)\n\n##### Rust (Synchronous)\n\n[code example]"
    },
    {
      "id": "watch-keys-for-changes",
      "title": "Watch keys for changes",
      "role": "content",
      "text": "Redis supports *optimistic locking* to avoid inconsistent updates\nto different keys. The basic idea is to watch for changes to any\nkeys that you use in a transaction while you are processing the\nupdates. If the watched keys do change, you must restart the updates\nwith the latest data from the keys. See\n[Transactions](https://redis.io/docs/latest/develop/using-commands/transactions)\nfor more information about optimistic locking.\n\nThe example below shows how to use the `transaction()` function to\nautomatically retry a transaction when watched keys are modified.\nPass the list of keys you want to watch and a closure representing the transaction.\nThe closure receives the original connection and a pipeline as parameters.\nUse the connection to read the latest values from the watched keys,\nbut always use the pipeline to add all the commands that make up the watched transaction.\nIf the watched keys are modified during the transaction, the `transaction()` function\nautomatically retries the transaction until it succeeds.\n\nOptimistic locking: Monitor keys for changes and retry the transaction when conflicts occur\n\n**Difficulty:** Intermediate\n\n**Available in:** Rust (Synchronous)\n\n##### Rust (Synchronous)\n\n[code example]"
    }
  ],
  "examples": [
    {
      "id": "execute-a-pipeline-ex0",
      "language": "rust",
      "code": "// Check the success of the pipeline without checking the results\n        // individually.\n        match redis::pipe()\n            .set(\"seat:0\", \"#0\")\n            .set(\"seat:1\", \"#1\")\n            .set(\"seat:2\", \"#2\")\n            .set(\"seat:3\", \"#3\")\n            .set(\"seat:4\", \"#4\")\n            .exec(&mut r)\n        {\n            Ok(_) => {\n                println!(\"Pipe executed successfully\");\n            },\n            Err(e) => {\n                println!(\"Error executing pipe: {e}\");\n                return;\n            }\n        };\n        \n        // Check the success of the pipeline and the results individually.\n        let (seat_0, seat_1, seat_2, seat_3, seat_4) :\n        (String, String, String, String, String) = match redis::pipe()\n            .get(\"seat:0\")\n            .get(\"seat:1\")\n            .get(\"seat:2\")\n            .get(\"seat:3\")\n            .get(\"seat:4\")\n            .query(&mut r) {\n                Ok(res) => res,\n                Err(e) => {\n                    println!(\"Error executing pipe: {e}\");\n                    return;\n                }\n            };\n\n        println!(\"{seat_0}, {seat_1}, {seat_2}, {seat_3}, {seat_4}\");\n        // >>> #0, #1, #2, #3, #4\n\n        // Use `ignore()` to ignore the result of specific commands.\n        let (seat_5, seat_6, seat_7) :\n            (String, String, String) = match redis::pipe()\n            .set(\"seat:5\", \"#5\").ignore()\n            .set(\"seat:6\", \"#6\").ignore()\n            .set(\"seat:7\", \"#7\").ignore()\n            .get(\"seat:5\")\n            .get(\"seat:6\")\n            .get(\"seat:7\")\n            .query(&mut r) {\n                Ok(res) => res,\n                Err(e) => {\n                    println!(\"Error executing pipe: {e}\");\n                    return;\n                }\n            };\n\n        println!(\"{seat_5}, {seat_6}, {seat_7}\");\n        // >>> #5, #6, #7",
      "section_id": "execute-a-pipeline"
    },
    {
      "id": "execute-a-transaction-ex0",
      "language": "rust",
      "code": "match redis::pipe()\n            .atomic()\n            .incr(\"counter:1\", 1)\n            .incr(\"counter:2\", 2)\n            .incr(\"counter:3\", 3)\n            .exec(&mut r)\n        {\n            Ok(_) => {\n                println!(\"Transaction executed successfully\");\n            },\n            Err(e) => {\n                println!(\"Error executing transaction: {e}\");\n                return;\n            }\n        };",
      "section_id": "execute-a-transaction"
    },
    {
      "id": "watch-keys-for-changes-ex0",
      "language": "rust",
      "code": "let key = \"shellpath\";\n        let _: () = r.set(key, \"/usr/syscmds/\").unwrap();\n        \n        let Ok(_,): Result<((),), _> = redis::transaction(&mut r, &[key], |r, pipe| {\n            let mut path: String = r.get(key).unwrap();\n            path.push_str(\":/usr/mycmds/\");\n            pipe.set(key, path).query(r)\n        }) else {\n            println!(\"Error executing transaction\");\n            return;\n        };\n\n        match r.get(\"shellpath\") {\n            Ok(res) => {\n                let res: String = res;\n                println!(\"{res}\");\n                // >>> /usr/syscmds/:/usr/mycmds/\n            },\n            Err(e) => {\n                println!(\"Error getting shellpath: {e}\");\n                return;\n            }\n        };",
      "section_id": "watch-keys-for-changes"
    }
  ]
}
