RustでMomentoのコレクションデータ型を試す

2023.01.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Introduction

高速サーバレスキャッシュサービスMomentoの情報です。
最近のアップデートにより、コレクションデータ型がサポートされました。
今回はMomentoのRust用SDKを使って
コレクション型をつかったMomentoへのアクセスを試してみます。

[注意]
Momentoのコレクション機能は現在previewです。
2023年1月現在、この機能を使いたい場合は
support@momentohq.comに連絡する必要があるので
注意してください。

Environment

今回試した環境は以下のとおりです。

  • MacBook Pro (13-inch, M1, 2020)
  • OS : MacOS 12.4
  • Rust : 1.66.1
  • Momento SDK : v0.21.0

DevIOのMomento関連記事はここにあるので、
これらもご確認おねがいします。

Setup

まずはMomentoのセットアップです。
このあたりを参考に、
Momentoの認証トークンを取得しましょう。

トークンを取得したらコンソールで環境変数にセットしておきます。

% export MOMENTO_AUTH_TOKEN = <取得した認証トークン>

次に、CargoをつかってRustプロジェクトの作成と依存ライブラリの設定です。

% cargo new momento-rust && cd momento-rust
# Cargo.toml

[dependencies]
momento = "0.21.0"

[dependencies.uuid]
version = "1.2.2"
features = [
    "v4",                
    "macro-diagnostics", 
]

Try

ではコレクションをつかってみましょう。
基本的にはJavaScript用SDKと似ているのですが、
言語的な違いがあったりするので多少は違います。

とりあえず必要モジュールのimportとクライアントの作成をするコードです。

use std::collections::HashMap;
use std::env;
use std::time::Duration;
use uuid::Uuid;

use momento::{
    MomentoResult,
    response::MomentoDictionaryGetResponse,
    response::MomentoDictionaryGetStatus, 
    response::CollectionTtl, 
    response::SimpleCacheClient,
    response::MomentoError,
    SimpleCacheClientBuilder,
};

fn get_client() -> SimpleCacheClient {
    let auth_token = env::var("MOMENTO_AUTH_TOKEN")
        .expect("env var MOMENTO_AUTH_TOKEN must be set to your auth token");
    let item_default_ttl_seconds = 60;

    SimpleCacheClientBuilder::new(auth_token, Duration::from_secs(item_default_ttl_seconds))
        .unwrap()
        .build()
}

Dictionary

クライアントを取得したり、元になるDictionaryを作ります。

    //Get Momento Client
    let mut momento = get_client();

    //Create Cache
    let cache_name = Uuid::new_v4().to_string();
    match momento.create_cache(&cache_name).await {
        Ok(_) => println!("ok"),
        Err(e1) =>println!("error occurred"),
    }

    //Create Dictionary & Dictionary Name
    let mut dictionary = HashMap::new();
    dictionary.insert("key1".to_string(), "value1".to_string());
    dictionary.insert("key2".to_string(), "10".to_string());
    dictionary.insert("key3".to_string(), "value3".to_string());

    let dictionary_name:String = Uuid::new_v4().to_string();

キャッシュ名とDictionary名を指定して、
dictionary_set関数でHashMapをキャッシュに登録します。

    momento
        .dictionary_set(
            &cache_name,
            &*dictionary_name, //or dictionary_name.clone()
            dictionary,
            CollectionTtl::default(),
        )
        .await;

登録したDictionaryから値の取得です。
Vecで任意の数のキーを指定して取得することもできます。

    let resp = momento
        .dictionary_get(&cache_name, &*dictionary_name, vec!["key1","key3"])
        .await
        .unwrap();

レスポンスは下記のように個別の値を取得できます。

    ////MomentoDictionaryGetResponse
    match resp.result  {
        MomentoDictionaryGetStatus::FOUND => {
            println!("dictionary found!");
            if let Some(dictionary) = &resp.dictionary {
                println!("dictionary entries:");
                for (k, v) in dictionary.iter() {
                    let k_str = String::from_utf8_lossy(k);
                    let v_str = String::from_utf8_lossy(v);
                    println!("0: {:?} => {:?}", k_str, v_str);
                }
            }        
        }
        MomentoDictionaryGetStatus::MISSING => println!("dictionary missing!"),
        _ => println!("error occurred"),
    };

dictionary_incrementを使えば引数に指定したキーの値を増やします。

 //key2の値を50増やす
 let value = momento
         .dictionary_increment(&cache_name, &*dictionary_name, "key2", 50, CollectionTtl::default())
         .await
         .expect("Failed to increment dictionary key")
         .value;
    println!("{}",value); //60

Dictionaryから値を削除するにはdictionary_deleteを使います。

    //remove some fields
    momento.dictionary_delete(
             &cache_name,
             &*dictionary_name,
             Fields::Some(vec!["key1"]),
         ).await.unwrap();


    // remove entire dictionary
    momento.dictionary_delete(
             &cache_name,
             &*dictionary_name,
             Fields::<Vec<u8>>::All,
         ).await.unwrap();

Set

次はSetを使ってみます。
set_union関数でキャッシュ名、セット名とコレクションを渡します。

    let elements = vec!["a", "b", "c", "a", "d"];

    momento
         .set_union(&cache_name, set_name.clone(), elements, CollectionTtl::default())
         .await
         .expect("error");

set_fetch関数を使えばSet全体を取得します。

    let response = momento
         .set_fetch(&cache_name, set_name.clone())
         .await
         .expect("Failed to fetch");
     if let Some(set) = response.value {
         println!("set entries:");
         for entry in &set {
             println!("{:?}", String::from_utf8_lossy(entry));
         }
     } else {
         println!("Collection not found");
     }

Summary

今回はRustでMomentoのコレクションAPIにアクセスしてみました。
JavaScript用SDKと同じく、簡単にコレクションAPIがつかえます。
なお、Rust用SDKは頻繁に更新されてますのでご注意ください。

この記事でキャッシュに使用したMomentoについてのお問い合わせはこちらです。
お気軽にお問い合わせください。

References

Momentoセミナーのお知らせ

2023年2月21日(火) 16:00からMomentoのセミナーを開催します。
興味があるかたはぜひご参加ください。