Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Fukuoka.rb_0x100_LT.pdf
Search
Yusuke Iwaki
May 11, 2022
Technology
490
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Fukuoka.rb_0x100_LT.pdf
Yusuke Iwaki
May 11, 2022
More Decks by Yusuke Iwaki
See All by Yusuke Iwaki
Playwrightのソースコードに見る、自動テストを自動で書く技術
yusukeiwaki
15
7.3k
あなたのWebサービスはAIに自動テストしてもらえる?アクセシビリティツリーで読み解く、AIの『視点』
yusukeiwaki
1
9.3k
個人開発から公式機能へ: PlaywrightとRailsをつなげた3年の軌跡
yusukeiwaki
12
9.3k
Capybara+生成AIでどこまで本当に自然言語のテストを書けるか?
yusukeiwaki
7
6k
ChatGPTを個々人が使っていた組織から チームチャットにボットを棲まわせて みんなが活用する組織になるまでの変遷 ぜんぶ紹介しちゃいます
yusukeiwaki
0
3.6k
E2E testing on Rails 2023
yusukeiwaki
4
3.6k
Railsの システムテスト解剖学
yusukeiwaki
8
8.2k
RailsのSystem specから 🎭Playwrightを使う
yusukeiwaki
2
16k
puppeteer-ruby: Ruby/Railsのためのブラウザオートメーションツール
yusukeiwaki
0
1.9k
Other Decks in Technology
See All in Technology
「社外イベント=意識高い」の壁を壊せ!元々無関心だった僕らが部内で社外イベントを民主化して15人を連れ出すまで
say_no_w
0
160
Don't write the architecture only in the prompt.
neohsu
0
170
[FECONF-2026] 신대륙을 향한 카카오페이증권 프론트엔드 항해기 (이주승)
l1ghthouse
0
250
AIコーディングエージェント開発_全体像
happysamurai294
0
110
あなたのDartコードは丸見えかもしれない ~reFlutterで暴くFlutterアプリの中身と多層防御~
zozotech
PRO
0
400
「Learning Outcome」を書きたくない私が、Learning Outcomeと折り合いをつけるまで
mhlyc
0
250
[re:Invent2026事前勉強会(有志開催)]続きは、ラスベガスの廊下で / continue-in-the-vegas-hallway
sh_fk2
0
340
「作れる」と「リリースできる」の間にあったもの── PdMを外して見えた、PdMがやるべき仕事/Buildable ≠ Shippable: What Removing the PM Taught Me About the PM’s Job
yappli_developers
0
340
1週間、Opus封印でお願いします
kintotechdev
0
320
演劇と私とスクラム
chinmo
0
160
アカウント統制の健康診断
kenichinakamura
1
210
Maestro MCPとClaude Code Skillsによる自律的なE2Eテスト支援
asmz
0
300
Featured
See All Featured
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
460
Mobile First: as difficult as doing things right
swwweet
225
10k
Are puppies a ranking factor?
jonoalderson
2
4.1k
Making the Leap to Tech Lead
cromwellryan
135
10k
Building the Perfect Custom Keyboard
takai
2
920
StorybookのUI Testing Handbookを読んだ
zakiyama
31
7k
SEO for Brand Visibility & Recognition
aleyda
0
4.8k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
810
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
860
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
610
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.2k
Transcript
async/await Rubyでどう書く? Fukuoka.rb 0x100 LT @YusukeIwaki
About @YusukeIwaki • 仕事:天神にある会社で、Railsアプリケーションの開発 ◦ 生まれは富山、大学は京都、1社目は札幌、2018年に福岡に移住 • puppeteer-rubyとかplaywright-ruby-clientとか作ってる人 ◦ ブラウザを自動操作するやつ
◦ Rubyでブラウザ操作するのに、Selenium以外の選択肢を作りたい。
Fukuoka.rb 0x0100回おめでとうございます • Kaigi on Rails 2021登壇のきっかけは、Fukuoka.rbの夜会 ◦ 夜の23時まで開いているRubyコミュニティは多分ここだけ? ◦
福岡にゆかりのあるひともないひともつながれるRubyコミュニティは素晴らしい ◦ 今後もゆるゆるとRubyを盛り上げていきましょう
本日の話 async / await ってRubyだとどうやって使えばいいの?
JSの有名ライブラリ Railsから使いたい! →Rubyに移植したい! async Promise then catch Promise.all Promise.race await
おそらく以下のどっちかが現実解 • 思考停止でconcurrent-rubyを使う ◦ とくにRailsアプリケーションだったら手軽 • めっちゃ考えてAsync gemを使う ◦ シングルスレッド動作で最大限のパフォーマンスが出せる
(memo) ここまで1分
おさらい: RubyのThreadとFiber • Thread→思考停止で、2つ以上の処理を同時に流せる • Fiber→ゆずりあいで、2つ以上の処理をかわりばんこに流す ◦ 合言葉は Fiber.yield
% ruby fiber.rb 0 1 2 3 4 0 1
2 3 4 % ruby thread.rb 0 0 1 1 2 2 3 3 4 4
async/await in Ruby • 思考停止でconcurrent-rubyを使う ◦ Threadベース ◦ とくにRailsアプリケーションだったら手軽 •
めっちゃ考えてAsync gemを使う ◦ Fiberベース ◦ シングルスレッド動作で最大限のパフォーマンスが出せる
(memo) ここまで2分半
concurrent-rubyでの async/await Promise Concurrent::PromisesモジュールのFutureを使う。 https://github.com/ruby-concurrency/concurrent-ruby/blob/master/docs- source/promises.in.md
concurrent-ruby: 2種類のFuture Concurrent::Promises.future { ….. ; 123 } • 裏で処理をやって、結果として123を返す
• Thread.newと同じ使い勝手で、さらに実行結果をもらえるイメージ f = Concurrent::Promises.resolvable_future, f.fulfill(123) , f.reject(err) • スレッドセーフな箱を作って、結果123を別スレッドから入れてもらう • JSのPromiseのような使い勝手
concurrent-ruby: Futureのチェーン、結果待ち受け future.then { |result| … ; next_result }.then {
|next_result| … } • JSのPromise#then, Promise#catch に限りなく近い future.value! • futureの結果をもらう。 • futureの結果がまだ出ていない場合には、結果が出るまでブロッキング。 Concurrent::Promises.zip(future1, future2, …) • 全部の結果が出揃うのを待つ。JSのPromise.allと同じ。
async click(x, y) { const point = await clickablePoint(x, y)
await scrollToPosition(x, y) await Promise.all([ mouse.down(x, y), mouse.up(x, y), ]) } def click(x, y) Concurrent::Promises.future do point = clickable_point(x, y).value! scroll_to_position(x, y).value! Concurrent::Promises.zip( mouse.down(x, y), mouse.up(x, y), ).value! end end concurrent-rubyを使ったasync/awaitっぽい実装 ※ 擬似コードです
でも気をつけろ!concurrent-rubyはThreadベースだ!
None
None
Async gem https://rubykaigi.org/2019/presentations/ioquatix.html
ノンブロッキングI/Oを活用し、IO待ちの間に別の処理を行う • シングルスレッドのFiberベースなので、オーバーヘッドが非常に少ない Ruby 2.xで利用するときには ノンブロッキングI/Oベースの各種ライブラリを併用する必要がある Async gem
Async { … } / Async::Reactor.run { … } •
処理のかたまり(task)を定義する ◦ JSの async () => { … } と似ている • トップレベルで利用するときと、ネストで利用するときとで挙動が違う ◦ トップレベルで利用時・・・サブタスクが全部終わるまで待つ ◦ ネストで利用時・・・サブタスクを作成し、スケジュール ◦ これも JSの async function呼び出しの挙動と似ている Async gemの基本
q = Async::Queue.new, q.dequeue, q.enqueue(hoge) • q.dequeueを呼ぶと、誰かがq.enqueueするまで待つ • q.dequeueよりも先に誰かがenqueue(hoge)していたら、即座にhogeが返る •
ほぼPromise cond = Async::Condition.new, cond.wait, cond.signal(hoge) • cond.waitを呼ぶと、誰かがcond.signalするまで待つ • cond.waitよりも先に誰かがcond.signal(hoge)しても、signalは捨てられる • 自前でPromiseっぽい何かを作る材料になる Async::Barrier, Async::Semaphore • サブタスク全部が終わるまで待つ、サブタスクの同時実行数を制限する • Promise.all 的なものを作る材料になる Async gemを使って async/await Promise
async click(x, y) { const point = await clickablePoint(x, y)
await scrollToPosition(x, y) await Promise.all([ mouse.down(x, y), mouse.up(x, y), ]) } def click(x, y) Async do point = clickable_point(x, y).wait scroll_to_position(x, y).wait barrier = Async::Barrier.new barrier.async { mouse.down(x, y).wait } barrier.async { mouse.up(x, y).wait } barrier.wait end end Async gemを使ったasync/awaitっぽい実装 ※ 擬似コードです
でも気をつけろ!Async gemはFiberベースだ! • 思考停止で使うと、並列処理されない(当然) • 不用意にwaitすると、メインスレッドがブロックされ全部が動かなくなる • Ruby 2.7で使いたいならノンブロッキングI/Oベースのライブラリ導入に そこそこ対応工数がかかる
ただ、用途があえば • すんごい速い • すんごい安定 ◦ 「ときどき処理順序がひっくり返ってしまって困る・・・」のような Threadベースだと起きる問題がFiberベースでは起きない
(memo) ここまで4分
まとめ:async/await in Rubyの現実解 • 思考停止でconcurrent-rubyを使う ◦ とくにRailsアプリケーションだったらもともと入ってるので手軽 ◦ Threadベースなので、処理順序性の保証とかほぼない •
めっちゃ考えてAsync gemを使う ◦ Fiberベースのシングルスレッド動作で最大限のパフォーマンスが出せる ◦ JSのasync functionに近い動作 ◦ Ruby 2.7環境で既存のアプリケーションに導入するのは結構たいへん
DEMO