1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//!
//! Optimized Redis GET / MGET / SET / MSET commands utilizing SIMD JSON with NodeJS [bindings](https://www.npmjs.com/package/redis-simd-json)

use napi::bindgen_prelude::*;
use napi_derive::napi;
use redis::AsyncCommands;
use redis_swapplex::get_connection;
use serde_json::Value;

#[napi]
/// Get the deserialized value of a key
pub async fn get(key: String) -> Result<Option<Value>> {
  let mut conn = get_connection();

  let bytes: Option<Vec<u8>> = conn
    .get(key)
    .await
    .map_err(|err| Error::new(Status::GenericFailure, format!("{:?}", err)))?;

  if let Some(mut bytes) = bytes {
    let value: Value = simd_json::serde::from_slice(bytes.as_mut_slice())
      .map_err(|err| Error::new(Status::GenericFailure, err.to_string()))?;

    Ok(Some(value))
  } else {
    Ok(None)
  }
}

#[napi]
/// Get the deserialized values of a set of keys
pub async fn mget(keys: Vec<String>) -> Result<Vec<Option<Value>>> {
  let mut conn = get_connection();

  let data: Vec<Option<Vec<u8>>> = redis::cmd("MGET")
    .arg(&keys)
    .query_async(&mut conn)
    .await
    .map_err(|err| Error::new(Status::GenericFailure, format!("{:?}", err)))?;

  data
    .into_iter()
    .map(|bytes| {
      if let Some(mut bytes) = bytes {
        let value = simd_json::serde::from_slice(bytes.as_mut_slice())
          .map_err(|err| Error::new(Status::GenericFailure, err.to_string()))?;

        Ok(Some(value))
      } else {
        Ok(None)
      }
    })
    .collect::<Result<Vec<Option<Value>>>>()
}

#[napi]
/// Serialize and set the value at a key
pub async fn set(key: String, value: Option<Value>) -> Result<()> {
  let value = match value {
    Some(value) => Some(
      simd_json::to_vec(&value)
        .map_err(|err| Error::new(Status::GenericFailure, err.to_string()))?,
    ),
    None => None,
  };

  let mut conn = get_connection();

  let _: () = conn
    .set(key, value)
    .await
    .map_err(|err| Error::new(Status::GenericFailure, format!("{:?}", err)))?;

  Ok(())
}

#[napi]
/// Serialize and set the values of multiple keys
pub async fn mset(data: Vec<(String, Option<Value>)>) -> Result<()> {
  let data = data
    .into_iter()
    .map(|(key, value)| match value {
      Some(value) => {
        let bytes: Vec<u8> = simd_json::to_vec(&value)
          .map_err(|err| Error::new(Status::GenericFailure, err.to_string()))?;

        Ok((key, Some(bytes)))
      }
      None => Ok((key, None)),
    })
    .collect::<Result<Vec<(String, Option<Vec<u8>>)>>>()?;

  let mut conn = get_connection();

  let _: () = redis::cmd("MSET")
    .arg(&data[..])
    .query_async(&mut conn)
    .await
    .map_err(|err| Error::new(Status::GenericFailure, format!("{:?}", err)))?;

  Ok(())
}