Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

週刊Railsウォッチ: ruby_memcheckでネイティブgemのメモリリークを自動検出ほか(20230629後編)

こんにちは、hachi8833です。

週刊Railsウォッチについて

  • 各記事冒頭には🔗でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
  • お気づきの点がありましたら@hachi8833までメンションをいただければ確認・対応いたします🙏

TechRachoではRubyやRailsなどの最新情報記事を平日に公開しています。TechRacho記事をいち早くお読みになりたい方はTwitterにて@techrachoのフォローをお願いします。また、タグやカテゴリごとにRSSフィードを購読することもできます(例:週刊Railsウォッチタグ)

🔗Rails

🔗 RailsアプリをMRSKでデプロイする(Ruby Weeklyより)


つっつきボイス:「MRSKは以前取り上げた37signalsのデプロイツールですね(ウォッチ20230308)」「Capistranoの令和版的な、サーバー側の動作環境としてDockerを使う前提のdeployツールという感じですか」「個人アプリで気軽に使うところからやってみてもよさそう👍」

# 同記事より
[~/git/mrsk-example] +(main) mrsk init --bundle

Created configuration file in config/deploy.yml
Created .env file
Created sample hooks in .mrsk/hooks
Adding MRSK to Gemfile and bundle...
  INFO [55b3727e] Running /usr/bin/env bundle add mrsk as gregmolnar@localhost
  INFO [55b3727e] Finished in 3.111 seconds with exit status 0 (successful).
  INFO [12808c1a] Running /usr/bin/env bundle binstubs mrsk as gregmolnar@localhost
  INFO [12808c1a] Finished in 0.120 seconds with exit status 0 (successful).
Created binstub file in bin/mrsk

MRSKのREADMEは以下で読めます↓

Kamal README: 37signalsの多機能コンテナデプロイツール(翻訳)

🔗 factory_trace: factoryの利用状況をチェック(Ruby Weeklyより)

djezzzl/factory_trace - GitHub


つっつきボイス:「factory_bot用のツールです」「RSpecを実行するときに未使用のfactoryやtraitをチェックしてくれるのか、なるほど↓」「しかもFactoryTrace.startFactoryTrace.stopが使えるので、factoryが使われている場所を絞り込んだりもできるらしい: こういうツールがあってもよさそう👍」

# 同記事より
$ FB_TRACE=1 rspec
total number of unique used factories & traits: 3
total number of unique unused factories & traits: 3
unused factory admin => spec/factories.rb:10
unused trait with_address of factory admin => spec/factories.rb:11
unused global trait with_email => spec/factories.rb:16

🔗 rails_performance: パフォーマンス測定ツール(Ruby Weeklyより)

igorkasyanchuk/rails_performance - GitHub


つっつきボイス:「New RelicやDatadog的なリッチな画面で、外部ストレージに依存せずにセルフホステッドで使えるAPM(Application Performance Management)ツールという感じですね」「データはローカルのRedisに保存するのね: config.duration = 4.hoursという設定があるのでストレージは有限という前提っぽい」「ToDoがまだ結構ありますね」


同リポジトリより

# 同リポジトリより
RailsPerformance.setup do |config|
  config.redis    = Redis::Namespace.new("#{Rails.env}-rails-performance", redis: Redis.new)
  config.duration = 4.hours

  config.debug    = false # currently not used>
  config.enabled  = true

  # configure Recent tab (time window and limit of requests)
  # config.recent_requests_time_window = 60.minutes
  # config.recent_requests_limit = nil # or 1000

  # configure Slow Requests tab (time window, limit of requests and threshold)
  # config.slow_requests_time_window = 4.hours # time window for slow requests
  # config.slow_requests_limit = 500 # number of max rows
  # config.slow_requests_threshold = 500 # number of ms

  # default path where to mount gem,
  # alternatively you can mount the RailsPerformance::Engine in your routes.rb
  config.mount_at = '/rails/performance'

  # protect your Performance Dashboard with HTTP BASIC password
  config.http_basic_authentication_enabled   = false
  config.http_basic_authentication_user_name = 'rails_performance'
  config.http_basic_authentication_password  = 'password12'

  # if you need an additional rules to check user permissions
  config.verify_access_proc = proc { |controller| true }
  # for example when you have `current_user`
  # config.verify_access_proc = proc { |controller| controller.current_user && controller.current_user.admin? }

  # store custom data for the request
  # config.custom_data_proc = proc do |env|
  #   request = Rack::Request.new(env)
  #   {
  #     email: request.env['warden'].user&.email, # if you are using Devise for example
  #     user_agent: request.env['HTTP_USER_AGENT']
  #   }
  # end

  # config home button link
  config.home_link = '/'

  config.skipable_rake_tasks = ['webpacker:compile']
end if defined?(RailsPerformance)

「目先の費用を節約するためにセルフホステッドのAPMツールを使っても、その後の人件費がかさんだら帳消しになってしまうので、やはりNew RelicやDatadogのような実績のある有料APMサービスを使う方がいいと自分は思います」「それもそうですね」

参考: New Relic | スタック全体をモニタリング、デバッグ、改善
参考: クラウド時代のサーバー監視&分析サービス | Datadog

🔗 Sidekiqのエラーをリトライ後に出力する(Ruby Weeklyより)


つっつきボイス:「これはよくある話ですね: Sidekiqなどのジョブ管理でエラーを何も考えずにリトライすると永久ループになったりするので、リトライ条件を設定するなどの工夫が必要」

# 同記事より
class RetryError < RuntimeError; end

def retry_once_before_raising_error(exception)
  if retry_count < 1
    raise RetryError, exception.message
  else
    raise exception
  end
end
  1. retry_countをジョブに追加
  2. Sidekiqミドルウェアを作成
  3. Sidekiqでミドルウェアを使うよう構成
  4. リトライロジックとエラー抑制
  5. SentryのコンフィグでRetryErrorsを除外
  6. ジョブにリトライロジックを実装
    同記事見出しより

🔗 その他Rails


つっつきボイス:「今年4月に3.0が出た(ウォッチ20230530)ViewComponentが早くも3.2.0をリリースしていました」

ViewComponent/view_component - GitHub

実践ViewComponent(1): 現代的なRailsフロントエンド構築の心得(翻訳)


つっつき後に調べてみると、上のEvil Martiansの記事で言及されていた#1061(システムテストでのJS操作サポート)がViewComponent 2.79.0の時点でマージされていることに気づきました。今度調べてみたいです。

with_rendered_component_pathというメソッドを追加し、ブラウザ内でコンポーネントのJSインタラクション操作をテスト可能にした。このプルリクは、コンポーネントを取り込んで結果のHTMLを含むTempfileを作成するメソッドを追加する。その後、この結果のHTMLはcapybara経由でブラウザに読み込まれる。
動作については新しいtest_simple_js_interaction_in_browserテストで確認できる。

これは特に、単体テストしたい場合やJSと正しく動作することを確認したい場合などに有用だと思う。
これが適切な方向性かどうか、または全く異なる方向性かどうかフィードバックをもらえると助かる。
[904] Enable testing component JS interactions using new with_rendered_component_path method by edwinthinks · Pull Request #1061 · ViewComponent/view_componentより

# https://viewcomponent.org/guide/testing.html#component-system-testsより
class ViewComponentSystemTest < ViewComponent::SystemTestCase
  def test_simple_js_interaction_in_browser_without_layout
    with_rendered_component_path(render_inline(SimpleJavascriptInteractionWithJsIncludedComponent.new)) do |path|
      visit(path)

      assert(find("[data-hidden-field]", visible: false))
      find("[data-button]", text: "Click Me To Reveal Something Cool").click
      assert(find("[data-hidden-field]", visible: true))
    end
  end
end

🔗Ruby

🔗 ネイティブgemのメモリリークを自動検出する(Ruby Weeklyより)


つっつきボイス:「Shopifyのrailsscale.comブログ記事です」「ここで言うネイティブgemは、CやC++やRustなどで書かれてコンパイルされるコードが組み込まれたgemのことですね: pure Rubyなgemであればメモリ管理はRubyのGCがやってくれますが、ネイティブgemの場合はメモリリークの可能性があるため、それを自動検出したいという話のようですね」「修正前のチャートで一直線に増えているのはたしかにメモリリーク↓」

修正前:

修正後:

同記事より

「それでも昔のPassengerやUnicornなどで数リクエストごとにワーカーキラーでプロセスをkillしていた頃に比べれば随分マシになりましたよね」「そうそう」「メモリ肥大化につながるコードが書かれる可能性があるアプリでは今でもワーカーキラー的なものは有効」

「記事ではValgrindというツールを元にruby_memcheckというgemを作ったと書かれていますね」「nokogiriやlibxml2などいろんなgemのメモリリークをこのgemで発見したのか」

Shopify/ruby_memcheck - GitHub

参考: Valgrind - Wikipedia

🔗 TruffleRuby 22.3.0リリース


つっつきボイス:「OracleのGraalVMリリース記事↓で新しいTruffleRubyのリリースを知りました」「Oracleがお金をかけてTruffleRubyのメンテナンスを継続しているのは凄い」「今後もメンテナンスするのかな🤔」

参考: A New GraalVM Release and New Free License! | by Alina Yurenko | graalvm | Jun, 2023 | MediumRuby Weeklyより)

🔗 gruff: Rubyでチャート生成(Awesome Rubyより)

topfunky/gruff - GitHub


つっつきボイス:「Rubyでチャートを生成するということはサーバー側で静的な画像を生成する用途かな」「ブラウザでインタラクティブにやるならJavaScriptのChart.jsとかになるんでしょうね」「昔自分のときはRでやってたけど、今だとたいていPythonでやりそうな気もする」

# 同リポジトリより
require 'gruff'
g = Gruff::Line.new
g.title = 'Wow!  Look at this!'
g.labels = { 0 => '5/6', 1 => '5/15', 2 => '5/24', 3 => '5/30', 4 => '6/4',
             5 => '6/12', 6 => '6/21', 7 => '6/28' }
g.data :Jimmy, [25, 36, 86, 39, 25, 31, 79, 88]
g.data :Charles, [80, 54, 67, 54, 68, 70, 90, 95]
g.data :Julie, [22, 29, 35, 38, 36, 40, 46, 57]
g.data :Jane, [95, 95, 95, 90, 85, 80, 88, 100]
g.data :Philip, [90, 34, 23, 12, 78, 89, 98, 88]
g.data :Arthur, [5, 10, 13, 11, 6, 16, 22, 32]
g.write('exciting.png')


同リポジトリより

🔗 JRuby 9.4.3.0リリース(Ruby Weeklyより)


つっつきボイス:「少し前にJRuby 9.4でRuby 3.1互換になって以来着々とリリースされていますね(ウォッチ20221207)」「default gemやbundled gemもアップデートされている」「さっきのTruffleRubyもそうですが、JRubyが主にエンタープライズ方面で使われていることで活発にメンテナンスされているのはいい👍」

🔗CSS/HTML/フロントエンド/テスト/デザイン

🔗 nginxがHTTP/3を実験的にサポート


つっつきボイス:「お、nginxがHTTP/3を実験的にサポートですか」「お〜」「以下のイベントも開催されるそうです↓」

参考: パブリッククラウドにおけるQUIC現状確認2023年8月編 | CloudNative Days Fukuoka 2023

参考: HTTP/3 - Wikipedia
参考: QUIC - Wikipedia

「HTTP/3はUDPベースのQUICでやるのか」「AWSのALBでHTTP/3を公式に使えるかどうかが気になりますね」「探してみたけど、今のところCloudFrontのサポートだけみたい↓」」

参考: Amazon CloudFront が QUIC を利用した HTTP/3 のサポートを開始

「CloudFrontでHTTP/3をサポートしたとして、クライアントとCloudFront間はHTTP/3化されるけど、CloudFrontからOriginへの接続はALBなどを通すことになるでしょうね: すべての通信がHTTP/3になるというよりは、ハイブリッドでもいいのでやれるところからHTTP/3にしていこう、みたいな感じかな」「なるほど」「キャッシュできるファイル配信とかも考えるとそれでも充分クライアントの速度には寄与しそうですね👍」

🔗言語/ツール/OS/CPU

🔗 Stack Overflowのデベロッパーアンケート2023(JavaScript Weeklyより)


つっつきボイス:「Stack Overflowの今年のアンケート結果が発表されていました」「例によってどんな種類の母集団かといった部分に注意しておく必要はありますけど、こういうアンケートを見るのはいろいろ面白い」(以下延々)


同サイトより

🔗 atuin: シェル履歴の絞り込み検索


つっつきボイス:「BPSアプリチームのu-ichiさんがSlackに貼っていたツールです」「SQLite3に履歴を保存して検索で絞り込んだりサーバー経由で共有したりするのか」「少なくとも業務でアクセスするシェルの履歴を共有したいとは思わないかな: リモートのシェルで他のシェルの履歴が出るとむしろ混乱しそう」「それもそうですね」

「このツールに使い道があるとすれば、"どのカレントディレクトリで実行したコマンドか"で絞り込みできることかも」「あ、たしかに」「いろんなプロジェクトをやっているとディレクトリと無関係に履歴が残るけど、実行したときのカレントディレクトリを指定して絞り込める機能なら欲しいですね」


後編は以上です。

バックナンバー(2023年度第2四半期)

週刊Railsウォッチ: 書籍『The Rails and Hotwire Codex』、JavaScript Primer改訂2版ほか(20230622後編)

ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。

Rails公式ニュース

Ruby Weekly

Awesome Ruby

RubyFlow

160928_1638_XvIP4h

JavaScript Weekly

javascriptweekly_logo_captured


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。