DieselとはRust製のORMです。
Dieselを使ってTransaction内で外部のAPIを叩きたい。
その際に、特定のレコードは行ロックしておきたい。
その戻り値を使ってレコードを更新したい。
今回はその方法を書き溜め。
DieselのTransaction内はsyncのためawaitは使用できない。
reqwestを使うとした場合、blocking::Clientを使用する必要がある。
しかし、ActixWebを利用している場合では、そのままblockingを実行しようとするとコンパイルエラーになる。
async関数の中でtransactionを呼び出すことになるため、
色々試してみてたところRuntime Handleからspawn_blockingすることで対応可能だった。
handle.spawn_blocking(move ||
のところがポイントだと理解した。
tokioはversion 0.2, reqwestは0.1, dieselは1.4.4です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
async fn hoge(key_params: String) -> { let handle = tokio::runtime::Handle::current(); handle.spawn_blocking(move || { conn.transaction::<_, MyError, _>(|| { let mut user: User = users .filter(user_key.eq(key_params)) .for_update() .load::<User>(&conn)?.pop().unwrap(), }); let client = reqwest::blocking::Client::new(); let map: Param = Param { user_key: key_params } let body = client.post("https://example.com/get_uniq_key") .json(&map) .send()?; let j: Response = body.json()?; let mut update_user_params = UserUpdate { id: user.id, uniq_key: Response.uniq_key }; let updated_user = diesel::update(&user) .set(update_user_params) .load::<User>(&conn); Ok(()); }).await?; } |
Rust勉強しなきゃ...
じゃあね〜〜〜〜。