Layered Architecture / DDD を採用した、Rust + Axum + WebSocket のチャットアプリ Engawa ("縁側" in Japanese)
本プロジェクトは Cargo Workspace を使用した複数パッケージ構成です:
- packages/shared: 共通ユーティリティ(時刻管理、ロガー)
- packages/server: サーバアプリケーション(Layered Architecture による4層構造)
- packages/client: CLIクライアントアプリケーション
詳細は AGENTS.md および ソフトウェアアーキテクチャドキュメント を参照してください。
- Rust 1.90.0
- Axum 0.8.6
graph TD
%% 登場人物
Client1[Client 1(CLI Application)]
Client2[Client 2]
Client3[Client 3]
Server[Server]
%% データフロー
Client1 -->| メッセージ送信 | Server
Server -->| メッセージ受信 | Client2
Server -->| メッセージ受信 | Client3
- リアルタイムチャット:
- クライアント間でメッセージを送受信(送信者自身には送信されない)
- メッセージは送信者以外の全クライアントにブロードキャスト
- 参加者管理:
- 接続時に現在の参加者一覧を表示(
room-connected) - 新規参加者の入室通知(
participant-joined) - 参加者の退室通知(
participant-left) - 各参加者の入室タイムスタンプ(ミリ秒精度、JST)
- 接続時に現在の参加者一覧を表示(
- 接続管理:
- ユニークな
client_idによる識別 - 重複
client_idの接続拒否(HTTP 409 Conflict) - 自動再接続機能(5秒間隔、最大 5 回)
- TODO: exponential backoff にする
- ユニークな
- サーバ機能:
- グレースフルシャットダウン(Ctrl+C / SIGTERM)
- クライアント接続状態の管理
- メッセージタイプ:
room-connected: 初回接続時の参加者一覧participant-joined: 参加通知participant-left: 退出通知chat: チャットメッセージ
bin/server: WebSocket チャットサーバ。接続中のクライアント間でメッセージをブロードキャストします(送信者自身には送信されません)bin/client: インタラクティブなチャットクライアント。ユニークなclient_idで接続し、再接続機能を持ちます
- Rust 1.90.0
- Task 3.45.5
cargo fmt# Clippy(lint)
cargo clippy --workspace --all-targets --all-features
# フォーマット
cargo fmt# workspace 全体のテスト
cargo test --workspace
# cargo test でも OK
# 個別パッケージのテスト
cargo test -p server
cargo test -p client
cargo test -p shared# workspace 全体をビルド
cargo build --workspace
# cargo build でも OK
# 個別パッケージのビルド
cargo build -p server
cargo build -p client
cargo build -p sharedcargo run -p server --bin server
# ポート指定
cargo run -p server --bin server -- --p 8080help
cargo run -p server --bin server -- --helpcargo run -p client --bin client -- --client-id alice
# サーバURL指定
cargo run -p client --bin client -- --client-id alice --url ws://127.0.0.1:8080/ws
# 別ターミナルで起動
cargo run -p client --bin client -- --client-id bobhelp
cargo run -p client --bin client -- --help参考:The Cargo Book - Publishing Commands
ターミナルで cargo login 実行後、https://crates.io/me へ飛び、トークンを生成する。その後、ターミナルにトークンを貼り付けて Enter を入力し、Login token for crates-io saved と表示されれば OK。
cargo login
# please paste the token found on https://crates.io/me below
# Login token for `crates-io` savedcargo publish
Important
依存しているパッケージは後でリリースする必要がある。
依存先が crates.io に登録されていない場合、cargo publish が失敗する。
cargo publish --dry-run
# 依存関係を自動で解決して publish する
cargo publish
# 依存順序を守って publish する
cargo publish -p engawa-shared
cargo publish -p engawa-server
cargo publish -p engawa-client- Git tagging
cargo publishが失敗する場合があるので、cargo publishの後にリリース時点のコミットに tag を付与する。
# git tag & push
git commit --allow-empty -m "Release v0.0.1 :tada:"
git tag -a v0.0.1 -m "Release v0.0.1 :tada:"
git push origin v0.0.1
# untag
git tag -d v0.0.1
git push origin :v0.0.1- format / lint / check / test
task fmt
task lint
task check
task test- コミット前の全チェック
task ci- サーバの起動
task run-server
# host, port 指定
task run-server HOST=127.0.0.1 PORT=8080- クライアントの起動
task run-client
# client-id, URL 指定
task run-client CLIENT_ID=alice URL=ws://127.0.0.1:8080/ws
# デバッグ用途
task run-client-alice
task run-client-bob- タスク一覧
task- タスクの詳細
task --summary <task-name>
# 例
task --summary run-server
task --summary run-client