2023/11/04
目次
- 概要
- 型定義など
- handler定義
- Query定義
- KvsServer実装
- 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
各ハンドラはファイル名と関数名が同一であるため、扱いやすさのために視認性を以下のようにした。
src/handlers/mod.rs
mod get;
mod set;
pub use get::get;
pub use set::set;
src/handlers/get.rs
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())),
}
}
src/handlers/set.rs
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.概要#参考に集約します。