redis_cas/
lib.rs

1//! Redis native module to add support for compare and swap
2
3#[macro_use]
4extern crate redis_module;
5
6use redis_module::{alloc::RedisAlloc, Context, RedisError, RedisResult, RedisString, RedisValue};
7
8/// Compare and swap if current value unchanged
9pub fn cas(ctx: &Context, args: Vec<RedisString>) -> RedisResult {
10  match args.as_slice() {
11    [_, key, current, new_value] => {
12      if let RedisValue::SimpleString(value) = ctx.call("GET", &[key.try_as_str()?])? {
13        if value.eq(&current.try_as_str()?) {
14          let _ = ctx.call("SET", &[key.try_as_str()?, new_value.try_as_str()?])?;
15          return Ok(RedisValue::Integer(1));
16        }
17      }
18
19      Ok(RedisValue::Integer(0))
20    }
21    [_, key, current] => {
22      if let RedisValue::SimpleString(value) = ctx.call("GET", &[key.try_as_str()?])? {
23        if value.eq(&current.try_as_str()?) {
24          let _ = ctx.call("DEL", &[key.try_as_str()?])?;
25          return Ok(RedisValue::Integer(1));
26        }
27      }
28
29      Ok(RedisValue::Integer(0))
30    }
31    _ => Err(RedisError::WrongArity),
32  }
33}
34
35redis_module! {
36  name: "redis_cas",
37  version: 1,
38  allocator: (RedisAlloc, RedisAlloc),
39  data_types: [],
40  commands: [
41    ["cas", cas, "write fast", 1, 1, 0],
42  ],
43}