- Ruby / Rails関連
週刊Railsウォッチ: Rails 7.1.0.rc1と7.1.0.rc2がリリース、SQLite3コンフィグの最適化ほか(20131004)
こんにちは、hachi8833です。7.1.0.rc1とrc2が立て続けにリリースされました。もしかすると今週の金土に開催される開催される第1回Rails World 2023の場で正式版がリリースされるかも?
Rails 7.1.0.rc1 is out! Just in time for Rails World next week.https://t.co/2RwCNH614F #rails #rubyonrails
— Chris Oliver (@excid3) September 27, 2023
参考: Release 7.1.0.rc1 · rails/rails
Rails 7.1.0.rc2 🎉https://t.co/oF9kC2hmw8
— Yutaka Kamei (@_yykamei) October 2, 2023
参考: Release 7.1.0.rc2 · rails/rails
🔗Rails: 先週の改修(Rails公式ニュースより)
🔗 Active Jobのリトライオプションにwait: :polynomially_longer
を追加し、wait: :exponentially_longer
を非推奨化
動機/背景
このプルリクを作成した理由は、
wait: :exponentially_longer
というオプション名が、ジョブを再試行する頻度について誤解を招くため。Active Jobのバックオフ戦略は「多項式時間バックオフ(polynomial backoff)」である。この場合は四次関数時間(quartic backoff)バックオフとも言えるが、指数関数時間バックオフではない。
自分のチームが取り組んでいるアプリの一部(フランスの公共サービス予約管理システム)は最近、バックグラウンドジョブがタイムアウトして再試行を大量に繰り返し、キューがオーバーフローしたために一時的な停止状態に陥ったことがあった。
このインシデントについてポストモーテムを開催し、ジョブがどのぐらい速やかに再スケジュールされたかを調査した。最初の数回を試してみたところ、驚いたことに指数関数時間バックオフよりも遥かに短い時間でリトライしていた。これをきっかけにこの問題を調査した。
詳細
このプルリクは、ジョブが多項式時間バックオフで再試行されることを明示するためにオプション名を変更し、後方互換性のために従来のオプション名も引き続き動くようにする。
多項式時間バックオフと指数関数時間バックオフの違い
Active Jobで実装されているリトライの遅延時間は
retry_count**4
で多項式的に増加するが、古典的な指数関数時間の遅延は、通常2**retry_count
のように指数関数的に増加する(このGoogle Cloudのドキュメントページなどを参照)。指数関数時間バックオフは、最初の数回の試行の初期値が(多項式時間の場合と)一致しやすくなるように
4**retry_count
として実装されることもある(自分たちはこの実装を期待していた)。これらをまとめると、それぞれの戦略がリトライ間で待機する時間は次のようになる(ジッターを除く)。
retry_count: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, retry_count**4 delay: 1s, 16s, 1m, 4m, 10m, 22m, 40m, 1h, 2h, 3h, 4h, 6h, 8h, 11h, 14h, 18h, 23h, 1d, 2d, 2d, 4**retry_count delay: 4s, 16s, 1m, 4m, 17m, 1h, 5h,18h, 3d, 12d, 49d, 194d, 2**retry_count delay: 2s, 4s, 8s, 16s, 32s, 1m, 2m, 4m, 9m, 17m, 34m, 1h, 2h, 5h, 9h, 18h, 2d, 3d, 6d, 12d,
なお、興味深いことにAction Cableの場合はリトライ戦略で真の指数関数時間バックオフを使っている(詳しくは以下を参照)。
- コード:
actioncable/app/javascript/action_cable/connection_monitor.js:77
- テスト:
actioncable/test/javascript/src/unit/connection_monitor_test.js:17
これは命名ミスか、それとも本当のバグか?
これをバグと見なすべきか単なる命名エラーと見なすべきかで悩んだ。言い換えれば、期待と実装のミスマッチを是正するために、コードを
2 ** retry_count
(それとも4 ** retry_count
か?)に変更するべきか、それともオプション名を変更すべきかがわからなかった。少し調べてみたところ、主要なRubyライブラリのほとんどで多項式時間バックオフによる
retry_count**4
が事実上の標準になっていることに気付いた(興味があれば次のセクションで詳しく説明してある)。さらに、多項式時間バックオフと指数関数時間バックオフのどちらが優れているかを判断するのは真の難問であるらしい。一般的なRailsアプリケーションに適用できる明確な答えが存在するとは思えない。
しかしながら、オプション名から期待できるものを管理し、利用しているバックオフ戦略を明確にすることについては合理的だと思える。
そういうわけで、「壊れてなければ修正しない」精神に基づけば、自分にとって最も理性的な選択肢は、オプション名を明確なものに変更するが、実装(および後方互換性)を維持することである。
おそらくだが、Active Jobは真の指数関数時間バックオフ戦略を提供する組み込みオプションを新たに提供すべきではないか(これは別のissueで取り上げるべきかもしれない)。
追加情報
多項式時間バックオフと指数関数時間バックオフの混乱は、Rubyコミュニティ全体に大きく広がっているらしい。驚いたことに、他のRubyライブラリにも
retry_count ** 4 backoff
を「指数関数時間バックオフ」と呼んで使っているものいくつもあることが判明した。歴史的な興味としてこの起源を探ってみたところ、以下を見つけた。
- Increase job rescheduling timeouts · tobi/delayed_job@2309a94
- delayed_jobのこのコミットは2008年に最初に導入されたが名前すら付いていない
- refactor job object · tobi/delayed_job@266fc15
- このコミットでは誤って「指数スケール(exponential scale)」と記述されている
後にsidekiq、sneaker handler、resque-retryでも同様の実装が出現している(2016年にActive Jobに追加されるよりも前の時代)。
自分は、この混乱が生じている多くのプロジェクトでも同様のプルリクをオープンする予定。
なお数学マニアなら、指数関数時間の複雑性で計算を解けるアルゴリズムが、多項式時間でも解けるかどうかを判定するのは真の難問であると指摘したくなるかもしれない。
同PRより
つっつきボイス:「少々長めのプルリクメッセージです」「ややこしいけど、どうやらActive Jobのリトライ戦略のオプションに関連する修正ということかな」「リトライのwait: :exponentially_longer
の振る舞いが、その名に反して指数関数時間のバックオフではなく多項式時間のバックオフになっていたので、今後は適切なオプション名であるwait: :polynomially_longer
を使ってねということか」「wait: :exponentially_longer
は非推奨になったけど、振る舞いを変えていないのは影響が大きいからでしょうね」
# activejob/lib/active_job/exceptions.rb#L59
def retry_on(*exceptions, wait: 3.seconds, attempts: 5, queue: nil, priority: nil, jitter: JITTER_DEFAULT)
+ if wait == :exponentially_longer
+ ActiveJob.deprecator.warn(<<~MSG.squish)
+ `wait: :exponentially_longer` will actually wait polynomially longer and is therefore deprecated.
+ Prefer `wait: :polynomially_longer` to avoid confusion and keep the same behavior.
+ MSG
+ end
rescue_from(*exceptions) do |error|
executions = executions_for(exceptions)
if attempts == :unlimited || executions < attempts
retry_job wait: determine_delay(seconds_or_duration_or_algorithm: wait, executions: executions, jitter: jitter), queue: queue, priority: priority, error: error
else
if block_given?
instrument :retry_stopped, error: error do
yield self, error
end
run_after_discard_procs(error)
else
instrument :retry_stopped, error: error
run_after_discard_procs(error)
raise error
end
end
end
end
参考: 多項式時間 - Wikipedia
参考: 指数関数時間 - Wikipedia
「実装で素朴にリトライを立て続けに繰り返すとシステムに支障が起きるので、たとえば最初は1秒待ってリトライしたら次は2秒、次は4秒、次は8秒...みたいにリトライの待ち時間を逓増させることがよく行われていますよね」「その待ち時間をどう増やしていくかという戦略がオプション名と合っていないのを問題にしているのか」
参考: リトライ処理の効率的アプローチ「Exponential Backoff」の概要とGoによる実装 - Qiita
「プルリクにもあるこの表がわかりやすいと思います↓: 一番上は待ち時間を素朴に1秒ずつ増やしているけどリトライが頻繁すぎてしまう、2番目のretry_count**4
は待ち時間が急速に増えていく多項式時間バックオフ、3番目と4番目の指数関数時間バックオフだともっと急速に待ち時間が増えていく」「2番目のretry_count**4
と3番目の4**retry_count
は最初の5つの待ち時間が似ていますね」
retry_count: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
retry_count**4 delay: 1s, 16s, 1m, 4m, 10m, 22m, 40m, 1h, 2h, 3h, 4h, 6h, 8h, 11h, 14h, 18h, 23h, 1d, 2d, 2d,
4**retry_count delay: 4s, 16s, 1m, 4m, 17m, 1h, 5h,18h, 3d, 12d, 49d, 194d,
2**retry_count delay: 2s, 4s, 8s, 16s, 32s, 1m, 2m, 4m, 9m, 17m, 34m, 1h, 2h, 5h, 9h, 18h, 2d, 3d, 6d, 12d,
「ちなみに、四次関数時間のバックオフ(quartic backoff)と書かれているのを見たときに最初quadratic(二次関数時間)かなと思ったけど、コードがretry_count**4
なので四次関数でした」「たしかに」
「Rubyのライブラリにも多項式時間バックオフと指数関数時間バックオフの実装が取り違えられているものがあるとは知りませんでした」「プルリクの作者はこれらも是正するつもりなのか、すごい」「ところでプルリク最後の"多項式時間でも解けるかどうか"云々はP≠NP予想のことですよね」
🔗 SQLite3の結合演算子||
をアダプタのデフォルト関数に渡せるようになった
SQLite3アダプタで、結合演算子
||
を含むデフォルト関数を処理できるようになった。従来は、デフォルト関数で
"'Ruby ' || 'on ' || 'Rails'"
のように静的な文字列が生成されていた。
改修によって、"Ruby on Rails"
を適切にアダプタに渡して利用できるようになった。change_column_default "test_models", "ruby_on_rails", -> { "('Ruby ' || 'on ' || 'Rails')" }
動機/背景
SQLite3をproduction環境で利用する動きが広まっているが、Active Recordの
SQLite3Adapter
は、SQLiteエンジンのパワーと機能を十分に活用できていない。MySQLAdapter
やPostgreSQLAdapter
の機能と互換にする手始めとして、SQLite3Adapter
をレベルアップさせるためにいくつものタスクに取り組み始めている。詳細
手始めに、最初に見つけたもっともシンプルな改善に手を付けることで、RailsとActive Recordへの機能のアップストリームにはずみを付けることにする。SQLite3では、
CONCAT()
関数ではなく結合演算子||
を提供しているが、現在のアダプターはこの演算子を動的なデフォルト関数として認識しない。
同PRより
つっつきボイス:「このプルリクはSQLite3のアダプタに文字列結合用の||
演算子を渡せるようにしたシンプルな改修ですが、これは前哨戦で、次のプルリクがメインのようです」
🔗 SQLite3でsupports_insert_returning?
をサポート
supports_insert_returning?
(AbstractAdapter
)を完全に実装することで、SQLite3アダプタでも自動生成カラム(#48241)とカスタム主キーをサポートする。動機/背景
上の#49287の修正を踏まえて、これは自分が
SQLite3Adapter
をMySQLAdapter
とPostgreSQLAdapter
と同等の機能を持つようにするために行う最初のプルリクとなる。SQLite3は機能の豊富なデータベースエンジンであり、production環境での利用は増加の一途をたどっている。自分たちは、開発者にSQLite3の機能範囲とスコープを提供するためにRailsでのサポートを必要としている。
詳細
#48241では、Active Recordモデルの属性をデータベースのデフォルト値で自動的に埋める素晴らしい機能が導入された。当初この機能は
PostgreSQLAdapter
のみで実装されていた。
この振る舞いのためのSQLの基盤となる重要な機能はRETURNING
キーワードだが、これはSQLite 3.35.0 (2021-03-12)以降でサポートされている(参考)。このプルリクでは、以下を実装することで
SQLite3Adapter
でRETURNING
キーワードをフルサポートする。
ActiveRecord::ConnectionAdapters::SQLite3::DatabaseStatements#sql_for_insert
ActiveRecord::ConnectionAdapters::SQLite3::DatabaseStatements#returning_column_values
ActiveRecord::ConnectionAdapters::SQLite3Adapter#supports_insert_returning?
ActiveRecord::ConnectionAdapters::SQLite3Adapter#return_value_after_insert?
ActiveRecord::ConnectionAdapters::SQLite3Adapter#use_insert_returning?
いくつかのメソッドについて調整も行った。
追加情報
この取り組みは、#49287から始めた。
同PRより
つっつきボイス:「以前#48241で、7.1にPostgreSQLのRETURNING
を使った新機能が入ることになったんですが(ウォッチ20230621)、プルリク作者の@fractaledmindさんによると、新しいSQLite3でもRETURNING
が使えるとのことなので、このプルリクでSQLite3でも使えるようにしたそうです」「へ〜!」
「Railsブログの更新情報にはありませんでしたが、同じ@fractaledmindさんによる#49349も既にマージされています」「これは?」「SQLite3のコンフィグを見直してパフォーマンスを平均で2倍向上させたんだそうです」「SQLite3にめちゃ強そうな人だ」
「このプルリクによると、近年productionでのSQLite3の利用が増えているんだそうです」「本当かしら?自分はSQLite3をproductionでは使ったことないんですよね: 読み出し専用で使うとかならありかもしれないけど」「SQLite3はデータベースサーバーを立てずに使えますよね」「環境によってはSQLite3クライアントのライブラリもインストールしないといけなくなりますけどね」
参考: Sqlite & Rails in Production · The Ruby Dispatch -- fly.io Blog
参考: using sqlite3 as production database : r/rails -- reddit.com
「HerokuではSQLite3の利用が認められていないんですが↓、最近だとfly.ioなどでは使えるみたいですね」「いずれにしろSQLite3が用途に合うかどうかでしょうね」
参考: Heroku 上での SQLite | Heroku Dev Center
つっつきの後で#49349を読んでみました。
▶#49349(クリックして展開)
🔗 SQLite3アダプタのコネクション設定のパフォーマンスチューニング
Normal同期モードのWAL(Write-Ahead-Log: ログ先行書き込み)導入、ジャーナルサイズの上限設定、共有メモリバッファや共有キャッシュの設定の健全化によって、RailsアプケーションにおけるSQLite3のパフォーマンスを平均で2倍増しにする。
動機/背景
SQLite3を利用するRailsアプリケーションは、データベースが実行されるWebアプリケーションのコンテキストに対するチューニングが貧弱だった。現在のSQLite3のデフォルト設定は、後方互換性や本来の利用目的である組み込みシステムを対象に行われたものであり、Webアプリケーションでの利用に適していない。ありがたいことに、SQLite3は
PRAGMA
文で手軽に設定できる。学術文献、開発者の実体験、および私自身のブログにも詳しく書かれているように、SQLite3データベースを最低でも2倍のパフォーマンス向上を達成する最適化は簡単に行える。
このプルリクは、RailsのSQLite3コネクションのデフォルト設定を更新して、最新のRailsアプリケーションのコンテキストに合ったチューンナップを施す。
詳細
理解およびチューニングの必要なプラグマのうち、最も重要なのは
journal_mode
プラグマである。SQLite 3.7.0(2010-07-21)以降、アトミックトランザクションをサポートするWAL(Write-Ahead log)が提供されている。これはWebアプリケーションにおける推奨ジャーナルモードである。SQLite3ドキュメントには以下のように書かれている。WALを使うことで、ほとんどのシナリオにおいて著しく高速化される。
WALは、リーダー(reader)としてのコンカレンシーを増やし、ライターをブロックしない。ライターもリーダーをブロックしない。読み書きはコンカレントに行われるようになる。アプリケーションでWALを使うようにすれば、同期の設定を緩和するのが理にかなっている。
synchronous=NORMAL
設定は、WALモードで動作するほとんどのアプリケーションに適している。
NORMAL
同期モードにすると、SQLite3がディスクに保存する頻度が、書き込みごとに保存する場合よりも少なくなる。SQLite3は、ディスクへの書き込みを独自のアルゴリズムで「最も重要な瞬間」に行うようになっており、同期をwal_autocheckpoint
ページ単位で行う(デフォルトでは1000ページ)。つまり、wal_autocheckpoint
プラグマが変更されると、Normalモードの同期はその数ページ後に発生するようになる。したがって、速度を稼ぐために耐久性と引き換えにアグレッシブな方法を使うことになる。
ただし、SQLite3は耐久性低下を軽減するさまざまな処理も行っているので、実際には極端なエッジケースである。実際SQLite3は、潜在的なデータ損失はOSやファイルシステムの故障時にしか発生しないようになっており、プロセスがクラッシュしてもデータ耐久性に影響しない。したがって、この最適化は99%のケースを対象にしており、1%のケースは対象にしていない。これはRailsアプリケーションに適していると思われる。
journal_size_limit
プラグマは、ディスクファイル内で保持するWALデータの量をSQLite3に指定する。
-1
(デフォルト値)はデータ量に上限を指定しないことを意味するので、このディスクファイルは無制限にサイズが増加する。この設定は望ましくない。ディスクがログファイルでいっぱいになってアプリケーションのダウンタイムを経験したことがある人ならば、ファイルサイズを無制限にすると頭痛の種にしかならないことはおわかりだろう。適切なサイズでファイルサイズを制限する必要がある。
次は
mmap_size
プラグマ(名前の短縮が甚だしいので注意)。この設定は「メモリマップI/Oでアクセスされるデータベースファイルの最大バイト数」を制御する。詳しく説明すると長くなってしまうが、要はメモリマップI/Oを有効にすると、SQLite3が複数のプロセス間でデータを共有できるようになる。メモリマップはPostgreSQLのバッファプールと同様の役割を果たすので、無効にするのではなく、デフォルトのPostgreSQLバッファプール(128MB)と同じ安全な値に設定する必要がある。
最後の
cache_size
プラグマは、「SQLiteが一度に開くデータベースファイルごとにメモリ内で保持してよいデータベースディスクページの最大数」を設定する。
-2000
(デフォルト値)は負の数であり、SQLite3は負の値をバイト数の制限と解釈する。
正の数を指定すると、SQLite3はこれをページ数の制限と解釈する。
デフォルトの上限は、ページ数にかかわらず約2MB(2,048,000バイト)になる。
キャッシュサイズが大きくなってもページ間で分割されないようにするには、正の値を指定してキャッシュ制限をページ番号に設定すべき。自分はcache_size
として2000ページを指定することを推奨する。この場合、デフォルトのページサイズ4,096バイトにおけるキャッシュ上限は約8MB(8,192,000バイト)となる。
#49349より
🔗 ドキュメント更新
🔗 locals:
とlocal_assigns
のドキュメントを改善
動機/背景
新しいRuby構文のおかげで、パーシャルのローカル変数で興味深い可能性が示された。
詳細
local_assigns
のドキュメントに、Ruby 3.1のパターンマッチング代入との統合の可能性を追加した。Action Viewの概要ガイドに、
render
呼び出しにlocals:
オプションの説明を記述する方法を追加し、local_assigns
メソッドについても追加した。また、Ruby 3.1のパターンマッチング代入との統合の可能性についても概要を追加した。
同PRより
つっつきボイス:「ビューのパーシャルに渡すlocals:
にアノテーションを付けられる機能が7.1で入る予定なんですが(ウォッチ20220822)、そのあたりの機能のドキュメントが更新されました」「このアノテーション機能のこと知らなかったけど、よさそう!」「このときのつっつき会でも盛り上がりました」
<%# issues/_card.html.erb %>
<%# locals: (title: "Default title", comment_count: 0) %>
<h2><%= title %></h2>
<span class="comment-count"><%= comment_count %></span>
🔗 strict_loading
のドキュメントを更新
APIドキュメントに単数形の関連付けのコード例を追加。
APIドキュメントの
:n_plus_one_only
モードのコード例で、コメント読み込み時にエラーがraiseされていたのを修正。
strict_loading!
をガイドに追加。APIドキュメントのコード例に
to_a
を追加(関連付けの読み込みでエラーをraiseするため)
同PRより
つっつきボイス:「こちらもドキュメントの更新で、strict_loading!
をレコードで直接呼べる機能とmode: :n_plus_one_only
を指定するとN+1が発生したときだけraiseする機能がドキュメント化されたそうです」「お〜、ちょうど今N+1クエリをつぶしまくっているところなんですが、7.1がリリースされないと使えないんだろうか?」
つっつき後に、strict_loading!
とn_plus_one_only
はRails 6.1から使えると教わりました(#37400)。
# guides/source/active_record_querying.md#1782
user.strict_loading!(mode: :n_plus_one_only)
user.address.city # => "Tatooine"
user.comments.to_a # => [#<Comment:0x00...]
user.comments.first.likes.to_a # raises an ActiveRecord::StrictLoadingViolationError
🔗Rails
🔗 rc1で標準出力のログ情報が不足する問題(rc2で修正済み)
つっつきボイス:「Rails 7.1の全Changelogを読みながら7.1beta1やrc1で動かせるところを動かしているときに、そういえば以下のようなCompleted 200 OK
↓とかがいつの間にか表示されなくなっているなと思っていたら、rc1で同じ問題を踏んでいた人を上のDiscussionで見つけました」
Completed 200 OK in 979ms (Views: 374.4ms | ActiveRecord: 87.6ms | Allocations: 70836)
▶rc1実機の標準出力(クリックで展開)
bin/rails s
=> Booting Puma
=> Rails 7.1.0.rc1 application starting in development
=> Run `bin/rails server --help` for more startup options
DEPRECATION WARNING: !render.view_component is deprecated and will be removed from ViewComponent 4.0.0 (Use the new instrumentation key `render.view_component` instead. See https://viewcomponent.org/guide/instrumentation.html) (called from <main> at /Users/hachi8833/deve/rails/rails71trial/config/environment.rb:5)
Puma starting in single mode...
* Puma version: 6.4.0 (ruby 3.2.2-p53) ("The Eagle of Durango")
* Min threads: 5
* Max threads: 5
* Environment: development
* PID: 14920
* Listening on http://127.0.0.1:3000
* Listening on http://[::1]:3000
Use Ctrl-C to stop
Started GET "/" for ::1 at 2023-09-28 20:22:11 +0900
ActiveRecord::SchemaMigration Load (18.2ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Pattern Count (19.7ms) SELECT COUNT(*) FROM "patterns"
↳ app/controllers/proofreads_controller.rb:5:in `home'
Started GET "/assets/tailwind-85f1c8e82d5a5bdc07d4fae87d65f26698058d73.css" for ::1 at 2023-09-28 20:22:13 +0900
Started GET "/assets/es-module-shims.min-295257ea6e233f6a8d82987e4107c1b3f9ed62ea.js" for ::1 at 2023-09-28 20:22:13 +0900
Started GET "/assets/stimulus.min-4b1e420eb07f8afa5ce3620fe38b5e2d411bc3ec.js" for ::1 at 2023-09-28 20:22:13 +0900
Started GET "/assets/turbo.min-522dcb4760c129e3820867b4b126a3904bacf96b.js" for ::1 at 2023-09-28 20:22:13 +0900
/Users/hachi8833/.anyenv/envs/rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rack-3.0.8/lib/rack/file.rb:5: warning: Rack::File is deprecated and will be removed in Rack 3.1
Started PATCH "/check" for ::1 at 2023-09-28 20:22:26 +0900
Pattern Count (7.7ms) SELECT COUNT(*) FROM "patterns"
↳ app/models/pattern.rb:29:in `fetch_regex'
Pattern Load (4.1ms) SELECT "patterns"."id", "patterns"."regex", "patterns"."comment", "patterns"."posi_sample", "patterns"."nega_sample", "patterns"."hit_count", "patterns"."display_name", "patterns"."memorandum", "patterns"."category", "patterns"."color", "patterns"."created_at", "patterns"."updated_at" FROM "patterns" ORDER BY "patterns"."updated_at" DESC LIMIT $1 [["LIMIT", 1]]
↳ app/models/pattern.rb:29:in `fetch_regex'
Pattern Pluck (0.8ms) SELECT "patterns"."id", "patterns"."regex", "patterns"."comment", "patterns"."category", "patterns"."color" FROM "patterns"
↳ app/models/pattern.rb:30:in `block in fetch_regex'
Pattern Update All (6.3ms) UPDATE "patterns" SET "hit_count" = COALESCE("hit_count", 0) + $1 WHERE "patterns"."id" IN ($2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) [["hit_count", 1], ["id", 4], ["id", 6], ["id", 1], ["id", 10], ["id", 2], ["id", 3], ["id", 5], ["id", 7], ["id", 8], ["id", 9], ["id", 11], ["id", 12], ["id", 13], ["id", 14]]
↳ app/models/highlight_match.rb:39:in `proofread'
^C- Gracefully stopping, waiting for requests to finish
=== puma shutdown: 2023-09-28 20:22:52 +0900 ===
- Goodbye!
「どうやら以下のプルリクでActiveSupport::BroadcastLogger
を導入したときに、ログ情報が標準出力から欠落していたようです↓」「ありゃ、これは直して欲しいですね」
その後rc2で以下の修正がマージされ、標準出力にレスポンスが出力されるようになりました😂。
$ cat Gemfile|rg 7.1.0
gem "rails", "~> 7.1.0.rc2"
# ...
Rendered layouts/_nav.html.erb (Duration: 4.3ms | Allocations: 1111)
Rendered layouts/_footer.html.erb (Duration: 0.5ms | Allocations: 163)
Rendered layout layouts/proofreads.html.erb (Duration: 64.0ms | Allocations: 37943)
Completed 200 OK in 196ms (Views: 73.2ms | ActiveRecord: 23.9ms | Allocations: 70770)
🔗 SQLite3を使うRailsアプリを強化する(Ruby Weeklyより)
- 元記事: Enhancing your Rails app with SQLite: Array columns | Fractaled Mind
- 元記事: Enhancing your Rails app with SQLite: Performance metrics | Fractaled Mind
つっつきボイス:「上の@fractaledmindさんがSQLite3関連のプルリクにも貼っていた記事です」「SQLite3のチューニングにここまで情熱を注いでいるとは...すごい」「業務だとSQLite3の詳細部分をここまで追求する時間がなかなかなさそうですよね」
今回は以上です。
バックナンバー(2023年度第3四半期)
週刊Railsウォッチ: 7.1でバリデーションメッセージのアポストロフィ->カーリー置き換えが取り消しほか(20230928後編)
- 20230926前編 Rails 7.1がJavaScriptでBunサポートを追加ほか
- 20230914後編 Turbo 8のTypeScriptがJavaScriptに置き換わるほか
- 20230913前編 Active Recordのenumにエラーをraiseしないvalidateオプションが追加ほか
- 20230908後編 IRB 1.8.0でデバッグ機能強化、Ruby Prize 2023開催決定ほか
- 20230906前編 システムテストでPlaywrightをサポート、to_paramのデリミタを変更可能にほか
- 20230829前編 Active Storageのミラーアップロードが非同期に、Rackアプリを手作りほか
- 20230824後編 週刊Railsウォッチ: ArelでCAST関数サポート、webdrivers依存を解消、YJIT高速化ほか
- 20230823前編 Rails 7.0.7に含まれているRails 7.0.6のバグ修正ほか
- 20230809 Rails 7.0.5のcreate_association挙動変更取り消し、YJITの性能を最大限引き出す方法ほか
- 20230803後編 Railsフラグメントキャッシュ経由の情報漏洩に注意ほか
- 20230802前編 Active Storageバリアントの事前変換、Linkヘッダープリロードのオプトアウトほか
- 20230727後編 Rubyにdefp導入の提案、IRB 1.7.3リリースほか
- 20230725前編 config.autoload_libとconfig.autoload_lib_onceが追加ほか
- 20230721後編 Kaigi on Rails 2023プロポーザル募集、rubocop-magic_numbersほか
- 20230719前編 複合主キー関連の実装進む、Action TextでHTML5サニタイザほか
- 20230705後編 AWS LambdaでRailsをRackで動かすLambyほか
- 20230704前編 productionのforce_ssl=trueがデフォルトで有効に、rakeタスクをthorで書くほか
ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。
週刊Railsウォッチについて
TechRachoではRubyやRailsなどの最新情報記事を平日に公開しています。TechRacho記事をいち早くお読みになりたい方はTwitterにて@techrachoのフォローをお願いします。また、タグやカテゴリごとにRSSフィードを購読することもできます(例:週刊Railsウォッチタグ)