おもしろwebサービス開発日記

おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

`config.active_support.hash_digest_class = OpenSSL::Digest::SHA256` とはなんなのか

時折、仕事でRailsのconfig.load_defaultsのバージョンを上げていく作業をしています。具体的には上げるバージョンに含まれるそれぞれの設定の意味を理解して、影響範囲を把握したうえで一つづつPull Requestを作るようにしています。実際にやってみた感想としては、これはなかなか難易度が高くきちんと影響範囲を理解したうえで実施できているプロジェクトは少ないのではないか?と思いました。そこで、これからconfig.load_defaultsのバージョンを上げる人の役に立つようにブログエントリを書いてみた次第です。

今日はconfig.load_defaults 7.0に含まれるconfig.active_support.hash_digest_class = OpenSSL::Digest::SHA256を取り上げます。

config.active_support.hash_digest_class = OpenSSL::Digest::SHA256は、主にキャッシュのキーに対して利用するハッシュ関数をSHA256にする、というものです。もともとのハッシュ関数はMD5でしたが、Rails5.2でデフォルトSHA1に変更され、7.0ではSHA256になりました。

今回のハッシュ化の対象はキャッシュキーであるため、SHA1が脆弱なのが問題というわけではありません。Rails全体としてSHA256を使うようにするとセキュリティ標準を満たしているかどうかのチェックが楽になる、という理由で変更が反映されたようです。

Rails内で関連のある部分

Railsのコードを見る限り、利用している箇所は次の4箇所です。

基本的にこれらのキャッシュを利用していなければ問題なく設定を変更できそうです。

変更が影響する箇所の確認方法

キャッシュを利用しているかどうかは十分なテストカバレッジがあれば、次のようなモンキーパッチで確認できます*1。下記のコードでは、ActiveSupport::Digest.hexdigestを実行した場所をログに出力しています。もしCIで並列実行をしているようであれば、適宜ログをマージして確認してください。

# config/application.rb or config/initializers/something.rb

module MonkeyPatch
  def monkeypatch_logger
    @monkeypatch_logger ||= Logger.new(Rails.root.join('log/monkeypatch.log'))
  end
  
  def hexdigest(*)
    monkeypatch_logger.debug("ActiveSupport::Digest.hexdigest is called from: #{caller(2, 1).first}")
  end
end

class ActiveSupport::Digest
  class << self
    prepend MonkeyPatch
  end
end

テスト実行前に、次のようにキャッシュを有効かつキャッシュストアをNullStoreに設定しておくのを忘れないようにしましょう。

# config/environments/test.rb
config.action_controller.perform_caching = true
config.cache_store = :null_store

もし利用している箇所があったら、設定変更によりデプロイ後に関連するキャッシュがすべてinvalidになります。負荷が上がることが予想されるので、一時的にアプリケーションサーバやDBサーバを増強する必要がありそうです。

*1:「長いキャッシュキーを縮める」の箇所を除く

ginza.rb 第85回を開催してSolid Trifectaについて学んだ

Ginza.rb 第85回 - Solid Trifectaについて学ぶぞ - connpass

Rails8.0にはいったSolid3兄弟*1ことSolid Cache, Solid Cable, Solid Queueについて取り上げる回でした。まずはy-yagiさんがSolid CacheとSolid Cableについて資料を作ってくれたのでそれを見ながらワイワイしました。

Solid Cacheをきちんと使うにはDB側の設定を頑張る必要があり運用の難易度も高そうなので、HEYやBaseCampのようにRedisのメモリに乗り切らないくらいのキャッシュを使うのでなければRedisをストレージにしたほうがいいんじゃないか、などの話をしていました。運用の知見に関してはこれから公開されるものもあると思うので一旦それ待ちですかね。

Solid CableはそもそもAction Cableを使っている人自体少ないのでサクッと眺めて終わり。個人的にはSolid Cableを導入してredisの分のインフラコストを削減できて便利なんだけど、これは小さいサービスだからですね…。

Solid Queueについてはこないだのkaigi on railsでの僕の発表資料を見てから公式のREADMEを眺めていました。

37signals社的にはすでに十分な機能が入っており、機能追加PRがきてもマージするモチベがそんなにないんじゃないの?とかConcurrency controlsの使い所についての話をしていました。特定のユーザが一度に大量のジョブを実行するのを避ける、みたいな使い方なのかなあ。

第84回もやっていた

第84回の開催エントリ書くの忘れていました><kaigi on rails前で忙しかった記憶。

Ginza.rb 第84回 - Campfireのコードを眺めるぞ - connpass

次回

次回はRails8.0を題材にワイワイする予定です。日程は調整中。

*1:3連星という説もあります

Kaigi on Rails 2024で Sidekiq vs Solid Queueというタイトルで発表した

表題の通り、発表してきました。

Sidekiq vs Solid Queue | Kaigi on Rails 2024

スライドはこちら。

発表に至るまでの道のり

  • イベントの懇親会などでエンジニアの人と話しているときに「最近気になっているgemあります?」のような質問に「Solid Queueですかねえ」と返すと「なんですかそれ?」と聞かれたりする
  • イベントの懇親会などでSidekiqを使っている会社さんの中の人にProやEnterpriseつかってます?と聞くと「なんですかそれ?」と聞かれたりする
  • 新しいRailsで標準になったが、既存のRailsアプリケーションには影響がないもの(例: importmaps)に対して「Railsアップグレードするならこれ対応しないといけないですか?」と聞かれたりする

SidekiqとSolid Queueをお題にして話せばこの手の疑問を一気に解決できるかな、と考えたところで「Sidekiq vs Solid Queue」というキャッチーなタイトルが浮かんできて、これはプロポーザル通るだろうなという確信を得るに至りました。

さらにこれまでのバックグラウンドワーカーの変遷で少しずつ機能やインタフェースが洗練されてきたのと2024年現在の状況を踏まえてできたのがSolid Queueなんですよ、という説明をしたくてbackgrounDRbからのgemの解説を盛り込んだのですが、実際に資料を作ると時間の関係で歴史については大幅に説明を省略せざるを得なかったのが残念ポイントです。Delayed::JobのdelayメソッドについてとかResqueのジョブ実行ごとにforkする話とかしたかったのですが、それだと60分超の発表時間が必要なのでした…。

1日目

かつてないレベルで準備時間がなかったので、基調講演だけ聴いて残りは資料作成をしていました。発表者控室が用意されていておかげで作業に集中できて助かりました。

基調講演は、palkanの著書である Layered Design for Ruby on Rails Applicationsと主張は一貫しているんだけど本の内容そのままではなく、サンプルが複数ステップのフォームになっていて本を読んでいても楽しめる内容になっていてよかったな、と思いました。

Kaigi on Rails 2024に参加した - It's okay to be weird でnagatomiさんも書いてるけど、事前に講演者の著書を読むというプラクティスは現場での講演の理解度と楽しさが上がるので大変オススメです。

Layered Design for Ruby on Rails Applicationsは僕がこれまで読んできたRailsを拡張する系の本の中で一番自然にRailsを伸ばすやり方が採用されていて、日々の業務に組み込みやすいプラクティスが書かれている書籍なので日本語翻訳の話が進んでるっぽい?けど翻訳を待たずに原著を読む価値あるんじゃないかな、と思います。

僕は家族の写真以外に写真を撮る習慣が全然ないのですが、せっかくストラップの色分けなど rubyfriendsするための工夫があるのになにもしないのもつまらないな、と前回のRubyKaigiのときに思ったので懇親会のときに一回だけrubyfriendsしておきました。次回も思い出せたらrubyfriendsしておきたいところです。

そのほか懇親会では島田さんになるほどTCPソケット最高です!と感想を直接お伝えすることができたのがよかったです。自分が執筆した書籍、誰がどれくらい読んでいてどのような感想を持っているのかなかなかわからないので読んだものについてはなるべく感想をお伝えするのが良いな、と思いました。

僕は東京在住なのですが有明までの移動はそこそこ時間がかかるので、懇親会の会場であるワシントンホテルを予約*1していました。懇親会が終わってからエレベータで上にいくとすぐに部屋に入れて最高の体験。

2日目

資料も出来上がっているし発表練習もホテルで何度かできたので、かなりリラックスして発表に臨めました。できあがった発表内容はどちらかというと初心者〜中級者くらいに向けた内容になっていて聴いてくれた人たちにどれくらい刺さる話になっているか不安だったのですが、Xの反応などを見る限りそれなりに評価されたようで良かったです。

発表資料の最後のスライドにありますが、顧問先に週1程度の空きができるのでバックグラウンドワーカの話をもっと突っ込んで聞きたい、とか最新のRailsなんもわからんからキャッチアップしたい*2とかいう会社さんいたらなんらかの方法でお問い合わせください。

そしてKaigi on Rails2025へ

すでにKaigi on Rails 2025に情報がありますが、次回の開催は9/26~27なんですよね。そして僕の誕生日(かつ結婚記念日)は9月27日だったりします。なので来年はどういう形で臨むといいかな、と今から思案を巡らせているところです。(皮算用にも程がありますが)27日に登壇して家族とちょっと美味しいご飯を食べる、ができるといいかなあ。

*1:Kaigi on Railsの会場場所が公開されてすぐ

*2:ほかにもいろいろやります。詳細は https://blog.willnet.in/entry/2018/04/09/101808 参照

ginza.rb 第83回を開催してRails7.2のマイナーフィーチャーを学んだ

Ginza.rb 第83回 - Rails7.2のマイナーフィーチャーを学ぶぞ - connpass

第83回のお題は第82回に引き続いてRails7.2。メジャーフィーチャー以外の気になった変更についてgistにまとめたものを見ながらみんなで「これはいいですねえ」とか「これはどうなんだろうなあ」とか話していました。

gistはこちら。 Rails7.2のマイナーフィーチャーで気になったところ

gistははてなブログと違ってh2ヘッダのアンカーURLが取得しやすいので、あとでこの機能について誰かに話したい、となったときに便利。

時間がちょっと余ったので、やぎぬまさんの用意したgistも見てワイワイしました。'debug/prelude'の件とかconnectionの扱いが変わる件とかそういえばありましたね。

gistはこちら。 Ginza.rb 第83回向けの何か.

個人的な印象に残ったポイント

  • 7.1ではいったstrict localsについて、パースするのが大変じゃんという発想がなかった
  • render @postsのようにして部分テンプレートを描画するときに自動でpost_counter, post_iterationというローカル変数が生える、というのは知らない人が多そう

次回

次回は10月11日(金)に、Campfireのソースコードをみんなで眺める会をやる予定です。ご都合の合う人はお気軽にご参加ください(\( ⁰⊖⁰)/)

大阪Ruby会議04でRailsの関連について話してきました

表題の通り、先日開催された大阪Ruby会議04で「どうしてこうなった?から理解するActive Recordの関連の裏側」というタイトルで登壇させていただきました。

スライドはこちら。

登壇するまで

僕は常々なにかしらRails関連のテックな話がしたいな〜と思っています。以前ブログに書いたActive Recordで関連先を保存するときに気をつけることは自分的にはかなりの力作だったのですが、あんまり読まれてなさそうだったのでこの機会に解説をモリモリ足して発表するともう少し幅広い人にリーチできるかな、と思いプロポーザルを出してみました。そこまでキャッチーな話ではないので通る自信はなかったですが、結果として無事採択されてよかった。今回の発表は大阪Ruby会議04がなければ日の目を見なかった可能性は高いです。オーガナイザの皆様、貴重な発表の場をありがとうございます。

登壇資料はブログをベースにすればいいからすぐできるやろ、と甘く見ていたら発表にあたって調査が必要な箇所が複数あり結局ギリギリまでスライドを調整していました。プロポーザルを通すのはいいけど、通ると期限内にスライドを作らなければいけないという制約*1が毎回辛い><

登壇

前回の大阪Ruby会議03ではうっかり10分の発表枠を選択してしまい時間が足りずに大変だったので今回は即30分の発表枠を選びました。おかげで当日じっくり話すことができてよかった。前回に限らず最近は「時間が足りないので急いで話す」ことが多くなにも意識しないと急いで話してしまうため「ここで水を飲む」スライドをあらかじめ複数配置して強制的に一息つくようにしていました。一定の効果があったので次回もやりたい。

登壇内容は上でも書いたようにRailsの関連についてでした。Railsの関連は「普段とくに内部実装を意識することなく頻繁に使っているけど、意識し始めると無限に疑問が出てくるし内部実装について言及しているドキュメントはほぼないしコードを読んで理解するのも難易度が高い」機能になっています。30分ですべてを説明することは難しいのですが、関連実装の中でも特に難しいと個人的に思っている関連先の自動保存と双方向の関連付けについて噛み砕いて説明することで、仮に昔の自分がこれを聞いたらめっちゃ満足するであろう話になりました。

しかし当日ちゃんとスケジュールを見てみるとスポンサーLTを除いてRailsの話をするのは僕だけ*2で参加者の需要に合った話だったかな…?と心配になりましたが、登壇後に役に立つ話だったと(はすみさん以外からも)何人か言及いただいたので安心しました。

今回は家庭の事情により次の日の朝すぐに東京に戻らないといけなくて大阪観光はほぼできず、という感じでしたが会場あたりの街並みがたぶん大阪に住んでいた頃に何度か通った場所で、懐かしい気持ちになりました。来年はもうちょっと余裕を持ってこれるといいな。

SaveChainInspector

関連先の自動保存がどのような順番で起きるのか調査するときに使えるsave_chain_inspectorというgemを紹介しましたが、現時点では出力を標準出力決め打ちにしていたりとだいぶ素朴な実装になっています。個人的には現状の仕様で困っていないのですが、需要があったらログファイルに出力もできるようにするなどしてもいいかな、と思っているので需要があったらその旨教えて下さい :pray:

次回予告

次の登壇はKaigi on Rails 2024で「Sidekiq vs SolidQueue」というタイトルで話す予定です。これから登壇準備を頑張ります。

*1:制約ではない

*2:強いて言えばkinoppydさんがRails周辺の話であるHotwireの話をしている

ginza.rb 第82回を開催した

Ginza.rb 第82回 - connpass 第82回のお題はもうじきリリースされるはずのRails7.2。やぎぬまさんがRails7.2メジャーフィーチャについてのスライドを作ってくれていたのでこれに沿ってワイワイしました。

メジャーフィーチャーという建付けだけど機能というよりは「rails newのときに新しいなにかが生成されるようになった」というものが多く、これはもしかしたらサラッと30分くらいで終わるかもしれないな〜と思ったので マイナーフィーチャー用の資料を用意していたのだけど、いい感じに時間いっぱいまで盛り上がって終了。マイナーフィーチャーに関しては来月持ち越し。

メジャーフィーチャー中のトランザクション中でエンキューしないという機能は個人的には最高便利!と思っていたのだけど、「トランザクション中でエンキューが失敗したらロールバックする」ができなくなるというデメリットについて話が出て「その発想はなかったなあ」となりました*1

来月はRails7.2のマイナーフィーチャーについてワイワイする予定なので都合合う方はご参加ください。

*1:sidekiq pro以上を使っていれば Reliability Client でエンキューの失敗をサポートできる気もしないでもないけど

ginza.rb 第81回を開催した

コロナ禍から休止状態だったginza.rbを4年ぶりに復活させました。

Ginza.rb 第81回 - connpass

コロナ禍以降リモートで働くひとが増えたので都内でオフラインミートアップをしても集まらないんじゃないかな?と思っていたのですが、蓋を開けてみたら定員オーバーするレベルで嬉しい誤算でした。開催してみた感想はオフラインミートアップからしか取れない栄養素あるな〜でした。復活させてよかった。

今回のミートアップの内容は久しぶりの開催なのでみんなの近況を聞きたいな、と思い自己紹介拡大版としました。みなさんかわらず元気にやっているようでよかった。

自己紹介タイムのあと、僕のプライベートが忙しくなったこともあり再開にあたってなるべく省エネでミートアップできる方法ないかなあ…というのを相談させてもらいました。ただginza.rbらしさをキープしつつ省エネするのはなかなか難しいですねという感触。ありがたいことにこれまでのginza.rbの内容を評価してくれる声もあったのでしばらく従来通り開催しつつ様子を見ようかな、と思っています。

次回はRails7.2をお題にして7月26日(金)に開催する予定です。お題がキャッチーなときは公開してすぐ枠が埋まりがちなので、参加するモチベが高い人はginza.rbのslackやconnpass*1などに登録しておいて通知を受け取れるようにしておくとよいかと思います。

*1:再開にあたってdoorkeeperから移行しています