- 前説:Rust+TCP/IP接続実現
- Rust+MariaDBのゴールはまだ先にあるのかと
- Cargo.toml の修正
- main.rs の修正後プログラム
- アレコレの説明(だいぶcopilotに助けてもらいました)
- 「sqlx」はバグ潰しに獅子奮迅の活躍
- 「tokio」は非同期処理の要
- query_as!+struct など先はまだある...
前説:Rust+TCP/IP接続実現
これまでの記事で、Linux_mint+MariaDB+Rust+mysql+TCP/IPを実現しました。Rust+TCP/IP実現まで、爺はかなり疲れたですけど、できて良かったです。
まとめ:Linux Mint で MariaDB 接続トラブル解消記(Rust対応) - pagetakaBlog
追補:Linux_mint+MariaDB+Rust+TCP/IP+mysql 準備編 - pagetakaBlog
Rust+MariaDBのゴールはまだ先にあるのかと
RustでRDB(リレーショナルデータベース)操作するとなると、目指す先には、課題が随分あると思う爺です。Linux_mint+MaraiDB+Rust+sqlx+tokio+query_as!+struct。 日付、Decimalなど型処理まで含めたら断崖絶壁かもしれませぬ。
「無料OS、RDB、Rustで、非同期処理し構造体に収めたい」という妄想を現実に引き寄せたい爺です。
今回は、非同期接続・処理に必要な最低限「tokio+sqlx」を実現します(query_as!、structなどはお預け)。
同期接続のプログラム(main.rs)と依存関係(Cargo.toml)を、最小限の修正で、非同期に変更します。
同期用プログラム改修で非同期用に変更します。
- 同期接続用プログラム:main.rs掲載の記事
- localhost用で書いているのをTCP/IP用に修正(紹介記事の下の方にご紹介)
- 依存関係:Cargo.toml掲載の記事
Cargo.toml の修正
dependencies欄の、同期用のmysqlドライバの記述を消去し、非同期用のsqlx+tokioに変更
- Cargo.toml ↓
(package略)
[dependencies] # 書けば、コンパイル時に公式からDL、インストールしてくれる
sqlx = { version = "0.7", features = ["runtime-tokio", "mysql"] }
tokio = { version = "1", features = ["full"] }
main.rs の修正後プログラム
説明よりまず動かしてみる、ですね。
use sqlx::mysql::MySqlPoolOptions;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Hello, async sqlx!");
let url = "mysql://user名:password@192.168.x.x:3306/db_name";
// 非同期コネクションプール
let pool = MySqlPoolOptions::new()
.max_connections(5)
.connect(url)
.await?;
// SELECT id, val FROM test LIMIT 1
let row = sqlx::query_as::<_, (i32, i32)>(
"SELECT id, val FROM test LIMIT 1"
)
.fetch_optional(&pool)
.await?;
match row {
Some((id, val)) => println!("id:{}, val:{}", id, val),
None => println!("データがありません"),
}
Ok(())
}
アレコレの説明(だいぶcopilotに助けてもらいました)
同期TCP/IP接続でDATABASE_URLをすでに実行
同期接続でTCP/IPを使用してますので、非同期処理導入に際し、「IPアドレス(database_url)」変更ありません。同期から非同期に変更するとき時々話題に上がるRDBの「IPアドレス(database_url)」ですが、予習・予行がすんでました。
非同期処理はRust側の待ち時間活用優等生
同期/非同期処理の違いは、Rust側待ち時間の使い方です。爺は、MariaDB側のコトかと妄想してましたが、Copilotに「Rust が待ち時間をどう扱うか」 と教えてもらいました。
フードコートで例えてみます。
- 非同期:料理出来たらスマホに連絡あるので、それまでは自由に席で過ごせる
- 同期:カウンターで注文し、料理ができるまでそのまま待つ
スマホに連絡来るなら、待ち時間にSNS発信するなど隙間時間利用できます。
Rustプログラム内でも同じで、
- 非同期:MariaDBへ接続・処理を依頼したら、結果が返えるまで、別処理(主にプログラム後続行)を進行しつつ、呼出しを待つ
- 同期:MariaDBへ接続・処理を依頼したら、結果が返るまでジッと待つので、隙間時間利用ができてない
という状態のようです。「スマホ呼出し」って、爺的にはずいぶん新しいコトでっす。待ち時間にほかの作業進行。これは、プログラム全体のスピードUPに結び付く可能性が高いですよね。ぜひ、マスターしたい「非同期」です。
同期で書いたプログラムを多少修正すれば、非同期処理になり、待ち時間が減り、Rustらしさに「半歩」近づきました。
「sqlx」はバグ潰しに獅子奮迅の活躍
「sqlx」は追加の道具(crate)で、Pythonのパッケージをインストールして使うのと同じ感覚です。
非同期処理では、tokio+sqlx の選択は「ほぼほぼ定番」のようです。
sqlxのありがた味は「バグ潰し」です。
- コンパイル時に密かにRDBに接続し
- SQLバグが無いかチェックしてくれ
- 実行したら落ちる、という悲劇を回避
Rustの厳格さを体現した逸品です。
「tokio」は非同期処理の要
Rustの非同期処理は、「async/await」の文法、実際に動かす「tokio」エンジンの組合せでなりたってます。
- async/await:Rustが「料理できたらスマホに連絡してネ」というオヤクソクのコトバ
- tokio:その通知を受取り、「連絡通知を頂いたら、すぐRustさんに知らせまっす」と段取りしてくれる「呼出し係」
async/await + tokio が Rustと一緒になって非同期処理してくれてます。
query_as!+struct など先はまだある...
前記事の「同期」から、今回「非同期」へと進行し、半歩前進できました。この次は、マクロquery_as!と構造体structを使いよりRustらしく前進させるのが、爺の妄想です。