---
# System prepended metadata

title: Rust Simple_Redis
tags: [simple_redis, Rust, redis]

---

###### tags: `Rust` `redis` `simple_redis`
# Rust Simple_Redis

Redisをより簡単に使うことのできるライブラリ
いわゆる、redis-rsのラッパー

```toml=
[dependencies]
simple_redis = "*"
```

# 概要
- 本家redis-rsほど包括的、柔軟ではない
- 一般的なユースケースをもっとシンプルなAPIで実装できる
- redisクライアントだけでAPI全体にアクセス
- pubsubインスタンスの管理が必要なく、クライアントだけですべて管理できる
- 自動で復元力がある内部接続とサブスクリプション
    - ここは本家redis-rsより上
    - 自動でつなぎ直すためのping操作コストが少し掛かる


# 注意点
simple_redisのクライアントには、Syncトレイトが実装されていないので
MutexやRwLock, Arcなどを使ってスレッドセーフなリソースにすることができない

db.rs などでグローバルなクライアント変数にするのではなく、
使うたびに client を接続することになる。

マルチスレッドにすると、クライアントがスレッドごとに作られて
同時接続数がすごいことになるので注意


# 使い方
## 接続
```rust=
extern crate simple_redis;
let client match simple_redis::create("redis://127.0.0.1/") {
    Ok(mut client) =>  println!("Created Redis Client"); client,
    Err(error) => println!("Unable to create Redis client: {}", error)
}
```

## Clientを使ったredis操作
詳しくは simple_redis の Client構造体の API Reference
https://docs.rs/simple_redis/0.3.44/simple_redis/client/struct.Client.html#method.get

## キーセット・取得
- 引数の型を自動変換
- 戻り値の型を明示的に指定

```rust=
match client.set("my_key", "my_value") {
    Err(error) => println!("Unable to set value in Redis: {}", error),
    _ => println!("Value set in Redis")
};

match client.get_string("my_key") {
    Ok(value) => println!("Read value from Redis: {}", value),
    Err(error) => println!("Unable to get value from Redis: {}", error)
};

// 数値型を扱う
match client.set("my_numeric_key", 255.5) {
    Err(error) => println!("Unable to set value in Redis: {}", error),
    _ => println!("Value set in Redis")
};

match client.get::<f32>("my_numeric_key") {
    Ok(value) => println!("Read value from Redis: {}", value),
    Err(error) => println!("Unable to get value from Redis: {}", error)
};
```
ポイント
- .set() : 任意の型の引数に対応
- .get::\<T>() : 任意の型をGET、ジェネリックパラメータで型を指定
- .get_string(): 必ずstring型で取得


## run_command() : 好きなコマンドを実行
```rust=
/// run some command that is not built in the library
match client.run_command::<String>("ECHO", vec!["testing"]) {
    Ok(value) => assert_eq!(value, "testing"),
    _ => panic!("test error"),
};
```

ポイント
- 戻り値の方を ::\<T> のジェネリックで指定
- 第一引数 = コマンド
- 第二引数 = vec! 引数


## pubsub

### publish
```rust=
/// publish messages
let mut result = client.publish("news_channel", "test message");
assert!(result.is_ok());
```
ポイント
- .publish()
    - 第一引数でチャンネル名
    - 第二引数でメッセージ

### subsclibe
まず、チャンネル名を指定してsubsclibeモードに
```rust=
/// subscribe to channels
result = client.subscribe("important_notifications");
assert!(result.is_ok());
// パターンマッチングでもsubscribeできる
result = client.psubscribe("*_notifications");
assert!(result.is_ok());
```

次に、 client.get_message(timeout)で待ち受ける

```rust=
loop {
    // fetch next message (wait up to 5 seconds, 0 for no timeout)
    match client.get_message(5000) {
        Ok(message) => {
            let payload: String = message.get_payload().unwrap();
            assert_eq!(payload, "my important message")
        },
        Err(error) => println!("Error while fetching message, should retry again, info: {}", error),
    }
}
```

ポイント
- timeoutには ミリ秒で待受時間を入れる
    - 0 だとタイムアウトなし(無限待ち)
    - タイムアウトするとErr()
    - 受信するとOk(message)
- message
    - redis-rs の Msg構造体と同じもの
    - .get_payload() : 中身を取り出す(Result)

