ys memos

Blog

Rustで簡単なKVSを実装してみた ~2. handler実装~


rust

2023/11/04


  1. 概要
  2. 型定義など
  3. handler定義
  4. Query定義
  5. KvsServer実装
  6. main&使ってみる

ここでは、RwLockを用いたReadロックやWriteロックのサンプルを含んでいる。


排他制御付きStoreに対するhandlerの実装である、src/handlers/*を記載する。

排他制御では、Arc<Mutex<Store>>ではなくArc<RwLock<Store>>とした。 これは、KVSという特性上、値の取得を気軽に行えるための配慮で、この選択により、複数のリーダーが同時にアクセス可能となる。


handlersのコード配置についてはかなり悩んだ。具体的に、query/handlersとするかどうかを考えたが、handlersはメソッドに対してKvsが割り当てる処理であるため、queryとは一線を画した配置をした。

このコード配置は、将来的にStoreにメソッドを実装するような設計への移行も見越しており、そのバランスからこのコード配置にした。

違う方向性としては、ソフトウェア全体の複雑性が増し、Methodに処理が紐付いていたほうが簡潔になるシチュエーションになれば配置場所もまた変えるべき可能性がある。


各ハンドラはファイル名と関数名が同一であるため、扱いやすさのために視認性を以下のようにした。

src/handlers/mod.rs
mod get;
mod set;

pub use get::get;
pub use set::set;

GETは読み込みのみであり、readロックを用いることにより、複数クライアントからのリクエストを同時に捌くことが可能。

src/handlers/get.rs
use std::sync::Arc;

use tokio::sync::RwLock;

use crate::{
    error::{KvsError, KvsResult},
    query::GetArgs,
    types::Store,
};

pub async fn get(store: Arc<RwLock<Store>>, args: GetArgs<'_>) -> KvsResult<String> {
    match store.read().await.get(args.key()) {
        Some(val) => Ok(val.clone()),
        None => Err(KvsError::KeyNotFound(args.key().into())),
    }
}

writeロックなので、同時に他のハンドラーを捌くことはできないので、若干コストが高い。

src/handlers/set.rs
use std::sync::Arc;

use tokio::sync::RwLock;

use crate::{error::KvsResult, query::SetArgs, types::Store};

pub async fn set(store: Arc<RwLock<Store>>, args: SetArgs<'_>) -> KvsResult<String> {
    store
        .write()
        .await
        .insert(args.key().into(), args.val().into());
    Ok("Succeed to insert".to_owned())
}

0.概要#おわりにに集約します。


0.概要#参考に集約します。

関連タグを探す