Rust のための証明駆動マイクロサービスフレームワーク
wakuwaku はサービスを組み立てるフレームワークです。gRPC サーバー、イベントハンドラー、cron ジョブといったすべてのコンポーネントを共有依存の型レベルレジストリから構築します。実際の処理を担うクレートは feature フラグの裏で再エクスポートされるので、サービスが依存するのは wakuwaku ひとつだけです。
依存はひとつだけ
wakuwaku を追加し、必要な連携機能を feature で有効にします。API に現れるサードパーティのクレートは wakuwaku::deps から再エクスポートされます。
- grpc· デフォルト
- proof· デフォルト
- iggy
- entity
- sqlx-pg
- sqlx-mysql
- redis
- meilisearch
[dependencies]
wakuwaku = { version = "1.0.0-rc2", features = ["iggy", "sqlx-pg", "redis"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread", "signal"] }証明駆動プログラミング
正しさを 2 つに分け、それぞれに適した方法で証明します。
マクロな正しさ
コンポーネント同士の組み合わせ方はトレイトで証明し、コンパイラーが検査します。登録されていない依存を使うコンポーネント、読み取り専用ハンドルで実行する書き込みクエリ、間隔がゼロの cron ジョブは、どれもビルドが通りません。
ミクロな正しさ
個々のコンポーネントの振る舞いはユニットテストで証明します。どのコンポーネントも Processor ベースのトレイトを実装したただの値なので、サービスを起動せずにテストから直接呼び出せます。
主な機能
フレームワーク本体がコンポーネントを組み立て、各連携機能はそれぞれのクレートとして feature フラグの裏で再エクスポートされます。
型レベルの依存レジストリ
ServiceBuilder共有依存は型でインデックスされたレジストリに置かれます。コンポーネントは ServiceCreation を通じてそのひとつから、または compose_* のクロージャで複数の依存から構築されます。参照はトレイトソルバーが解決するため、Any もダウンキャストも実行時のマップもありません。
詳しく見るgRPC サーバーの登録
feature = "grpc"レジストリから tonic のサーバーを構築し、登録順にひとつのルーターへまとめて追加します。Box 化も動的ディスパッチもありません。
詳しく見るcron ジョブ
CronJobジョブは定数 CronJobInterval を持つ CronTick のプロセッサーです。実行後に間隔を空ける、開始の間隔を最低限空ける、実行が重なりうる固定のグリッド、のいずれかを選べます。エラーやパニックはログに記録され、スケジュールは保たれます。
詳しく見るApache Iggy 上の型付きイベント
wakuwaku::iggy順序はパーティション単位ではなくキー単位で保証されます。順序フェンスが追い越しの可否を決め、代数マーカーによってポーリングしたバッチを畳み込み、ハンドラー呼び出しを減らせます。
詳しく見るケイパビリティで型付けされたデータアクセス
wakuwaku::entityクエリは読み書きするエンティティを宣言し、Db ハンドルはそれを満たすケイパビリティを持たなければなりません。sqlx(PostgreSQL・MySQL)、Redis、Meilisearch のデータソースを提供します。
詳しく見る証明付きバリデーション
wakuwaku::proofprove は値と、述語が成り立った証拠を組にした Proven<T, P> を返します。シグネチャで Proven を受け取れば、「検証し忘れ」は型エラーになります。
詳しく見るひとつのファイルでサービスを
共有の SessionStore から構築され、1 分ごとに実行される cron ジョブです。gRPC サーバーや Iggy のイベントハンドラーも同じ ServiceBuilder から登録します。
use std::time::Duration;
use wakuwaku::deps::kanau::processor::Processor;
use wakuwaku::{CronJob, CronJobInterval, CronTick, ServiceBuilder, ServiceCreation};
#[derive(Clone)]
struct SessionStore;
struct ExpireSessions { store: SessionStore }
impl ServiceCreation for ExpireSessions {
type Dep = SessionStore;
fn create_service(store: SessionStore) -> Self { Self { store } }
}
impl Processor<CronTick> for ExpireSessions {
type Output = ();
type Error = std::convert::Infallible;
async fn process(&self, _tick: CronTick) -> Result<(), Self::Error> {
// Scan for expired sessions and delete them.
Ok(())
}
}
impl CronJob for ExpireSessions {
const INTERVAL: CronJobInterval = CronJobInterval::AtLeast(Duration::from_secs(60));
}
#[tokio::main]
async fn main() {
let (services, cron) = ServiceBuilder::new(SessionStore)
.cron_job::<ExpireSessions, _>()
.start();
// Build gRPC servers and Iggy handlers from `services` the same way:
// `services.grpc_service::<XxxServer<_>, Impl, _>(XxxServer::new)`,
// `services.iggy_consumer::<Handler, _, _>()`, or from several
// services at once with `.compose_grpc_service(|s| ...)`.
let _ = services;
tokio::signal::ctrl_c().await.ok();
cron.shutdown().await;
}ロードマップ
目指すのは、Java における Spring のように強力で堅牢なフレームワークです。
- 1.0.0-rc1出発点
最初のリリース候補版です。
- 1.0.0-rc3現在
このドキュメントが対象とするリリース候補版です。
- 1.0.0安定版
実際のプロジェクトでの E2E テストを経てリリースします。
- 2.0.0Spring と同等
意味のある Spring モジュールすべてに wakuwaku の対応物がそろった段階です。