Slide 1

Slide 1 text

非同期jobをtransaction内で 呼ぶなよ!絶対に呼ぶなよ! Yuto Urushima(@alstrocrack)

Slide 2

Slide 2 text

Backend Engineer from Hubble 大学時代の専攻: 建築学 漆島 裕人 @alstrocrack

Slide 3

Slide 3 text

法務と事業部門の協業性を高め、 生産性を向上するための契約業務基盤を 実現・定着する契約書管理クラウド

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Ruby on Railsで開発していると 非同期jobの謎のバグに 遭遇しますよね??

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

非同期jobを呼ぶ前にuserをちゃんと createしているのになんで ActiveRecord::RecordNotFoundなんだ?

Slide 10

Slide 10 text

しかも、このエラーは再現する場合と 再現しない場合が存在するようなの で、ちょっとデバッグをしづらい…

Slide 11

Slide 11 text

transaction ACID特性とともにDB内の データの不整合を防ぐ処理 ここでCOMMIT処理が行われる (DBへ変更を書き込む)

Slide 12

Slide 12 text

非同期job 元の処理とは別のプロセスやスレッドで 実行する処理 タイミングはある程度任意であり、 エンキューされるといつ実行される か正確なところは分からない ここで実際の処理を定義

Slide 13

Slide 13 text

Timeline COMMIT job Start Transaction t 非同期job

Slide 14

Slide 14 text

Timeline COMMIT job Start Transaction t 非同期job

Slide 15

Slide 15 text

Timeline COMMIT job Start Transaction t 非同期job DBの変更よりも先に非同期job が開始しちゃっている

Slide 16

Slide 16 text

ActiveJob::DeserializationError 非同期job実行時に該当の レコードがDBに存在していない ActiveJob::Deserialization Errorが発生

Slide 17

Slide 17 text

じゃあ、これどうやって防ごうか?

Slide 18

Slide 18 text

対策 その1 非同期jobのエンキュー をtransactionの外に 記述する

Slide 19

Slide 19 text

GitHubのPull Request のテンプレート内で チェック項目にすれば 良いのでは?

Slide 20

Slide 20 text

対策 その2 gemの力を借りる (after_commit_everywhere など)

Slide 21

Slide 21 text

対策 その3 enqueue_after_transaction_com mitの設定を利用 ※Ruby on Rails 7 .2以降から利用可能 暗黙的な非同期jobの エンキューにも対応できる!

Slide 22

Slide 22 text

というわけで使ってみた

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

false

Slide 28

Slide 28 text

true

Slide 29

Slide 29 text

enqueue_after_transaction_commitの設定値の変遷 Rails 7.2系 現在

Slide 30

Slide 30 text

まとめ transaction内の非同期jobへのエンキュー処理は 実行タイミングによっては上手くいかない可能性があるので 対策しましょう!!

Slide 31

Slide 31 text

Thank you !