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

週刊Railsウォッチ: YJITがRuby 3.1向けにマージ、ripperのドキュメント化、crontabの罠ほか(20211026後編)

こんにちは、hachi8833です。

週刊Railsウォッチについて

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

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

🔗Ruby

🔗 YJITリーダーによるYJIT紹介記事


つっつきボイス:「以下↓はYJITリーダーであるMaxime ChevalierさんによるYJIT紹介記事ですが、翻訳リクエストを受けてひとまず一次翻訳終えました: リクエストありがとうございます🙏」「お〜翻訳楽しみ」「Ruby 3.1でYJITがマージする流れになっていますね: YJITはデフォルトでオフのはずなので、使わないときは意識せずに済むはず」「お〜YJIT楽しみ」

「続編記事としてNoah GibbsさんによるYJITお試し方法の紹介記事も出ていました↓」

以下はYJITのベンチマークサイトです。

🔗 YJITがマージされた

「ちなみについさっき(注: つっつき時点の10/21夜)YJITがマージされたというツイート↓を見かけたんですが、YJITがでかくてコミット数が多かったせいかdev環境のSlackボットや通知周りがエラーになって、いったんcloseされていました」「ありゃ残念」「ドンマイ」「分解するのは大変そう」

つっつきの後、無事YJITがmasterにマージされました🎉

参考: ruby-trunk-changes 2021-10-21 - ruby trunk changes

その後、OpenBSDでYJITを無効にするコミットや、JITでMJITを有効にするオプションを追加するコミットも追加されていました(YJITとMJITは同時には利用できないそうです)。

🔗 safe_regexp: 正規表現をタイムアウト

grosser/safe_regexp - GitHub

# 同リポジトリより
# normal
/a/.match?('a') # -> true in 0.0001ms
SafeRegexp.execute(/a/, :match?, 'a') # -> true in 0.13568ms

# bomb
require "safe_regexp"
regex = /aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?aa?/
value = "a" * 46
regex.match? value # false in ~60s
SafeRegexp.execute(regex, :match?, value) # -> SafeRegexp::RegexpTimeout

# methods without arguments
regex = "^(The '(?<first_group>.*)' parameter of the (?<second_group>.*))$"
SafeRegexp.execute(regex, :names) # -> ["first_group", "second_group"]

つっつきボイス:「以下のregular-expressions.infoというサイトで知りました↓: サイトの人がこのgemを試したかどうかまではわかりませんでしたが」「今日のBPS Webチーム内発表で触れていたgemですね」「SafeRegexpを使うことで、正規表現がデフォルトで1秒以上かかるとタイムアウトしてエラーをraiseするそうです」

参考: Preventing Regular Expression Denial of Service (ReDoS)

「今Ruby本家でも正規表現にタイムアウトを入れようかという話が出ていましたね」「はい、RubyKaigi Takeout 2021のMartin先生の発表↓で触れていた#17837などですね」「これは?」「最近流行りのcatastrophic backtracking攻撃に対してRubyが対抗策を議論しているissueのひとつです」

参考: Regular Expressions: Amazing and Dangerous by Martin J. Dürst - RubyKaigi Takeout 2021

「READMEではThreadTimeoutを使わずに作ったとありました」「同じくREADMEによると、正規表現用に別プロセスを立ち上げて、タイムアウトしたらkill -9で止めるということをやってるらしい: 正規表現エンジンの中にタイムアウトを仕込むのではなく、エンジンの外側でやるという戦略かな」「シェルで強制終了するような感じなんですね」

「そういえば手元でsafe_regexpをちょっと試してみたところ、ヤバいパターンを食べさせたらコンソールが固まって、Ctrl-Cでも戻らなくなっちゃいました😢」「kill -9で止めるしかないでしょうね: 別プロセスにしないとRubyのメインプロセスがCPUタイムを食い尽くしてしまうので、OSのことも考えて正規表現用のプロセスを分けたんでしょうね」「なるほど」

「重たい別プロセスをRubyで立ち上げるのは泥臭いですが、ひとつの方法でしょうね」「テスト環境で使うとか、特定の正規表現を手元で検証するときにはよさそう👍」

はじめての正規表現とベストプラクティス10: 危険な「Catastrophic Backtracking」前編

🔗 ripperのドキュメント化が進行中


つっつきボイス:「RubyのパーサーライブラリであるRipperは以前からドキュメントがないと言われていましたが、この方が頑張ってコードを読んでドキュメントを書き進めているそうです」「お〜すごい!」「READMEの内部リンクがまだ切れてるのでファイルを直接開いてください」

参考: class Ripper (Ruby 3.0.0 リファレンスマニュアル)

「RuboCopの作者の@bbatsovさんも、ドキュメントがないなどもろもろの理由でRipperを使うのをやめたそうです↓」「ドキュメントがなくても使う人はいるでしょうけど、やっぱりドキュメント大事」「動きがだいたいわかってても、ドキュメントがないと不安になりますよね」「RuboCopも使えるものならRipper使いたかったでしょうね」「ドキュメント化大変だろうけど頑張って欲しいです🙏」

RuboCop作者がRubyコードフォーマッタを比較してみた: 後編(翻訳)

🔗 Rubyのワンライナーcookbook


つっつきボイス:「Rubyのワンライナー向けオプションはたくさんある分、Perlの-pieオプションに比べると長めになってしまう傾向がありますけど、Rubyの-neオプションあたりなら使いますね」

# 同記事より
$ # sample stdin data
$ printf 'gate\napple\nwhat\nkite\n'
gate
apple
what
kite

$ # print all lines containing 'at'
$ # same as: grep 'at' and sed -n '/at/p' and awk '/at/'
$ printf 'gate\napple\nwhat\nkite\n' | ruby -ne 'print if /at/'
gate
what

$ # print all lines NOT containing 'e'
$ # same as: grep -v 'e' and sed -n '/e/!p' and awk '!/e/'
$ printf 'gate\napple\nwhat\nkite\n' | ruby -ne 'print if !/e/'
what

参考: Perlのワンライナーでテキストの一括置換 - console.lealog();

「Rubyは標準機能が強力だし普段からRuby書いてるので、ワンライナーにもいいですよね」「いいっす」「ただ自分がRubyであまりワンライナー書かないのは、カスタマイズできない作業環境でRubyが使えるとは限らないからというのもあるんですよ」「その意味ではPerl強いですよね」「Perlはたいていの環境で最初から使えますね」

「Pythonも入っているとは限らない」「あってもPython 2系か3系かという罠があったりしますし」「さすがに新しい環境でPython 2は減ったと思いますけど、古い環境だと油断できない」

参考: Python 2.7.x と 3.x の決定的な違いを例とともに | POSTD

「macOSだとRubyが入っているけど、バージョンが古いんですよね」「1.8とかだったらどうしよう」「1.8はもう別物😆」

後でBig Sur備え付けのRubyバージョンを調べてみました。Ruby 2.6は2022年3月にEOL(end-of-line)を迎えますが、果たしてmacOSはちゃんとバージョン上げてくれるでしょうか?
参考: Ruby Maintenance Branches

$ /usr/bin/ruby -v
ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin20]

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

🔗 セキュリティヘッダークイックリファレンス(StatusCode Weeklyより)


つっつきボイス:「HTTPのヘッダーのうち、セキュリティ関連のヘッダーのクイックリファレンスだそうです」「▼をクリックすると詳細が表示されるのね」

X-Content-Type-Optionsはたしかに使う」「X-Frame-Optionsもそういえばあった」

# 同サイトより
X-Content-Type-Options: nosniff
# 同サイトより
X-Frame-Options: DENY

「クロスオリジン関連のヘッダーにCross-Origin-Opener-Policy(COOP)やCross-Origin-Embedder-Policy(COEP)というのもあるんだ、へ〜細かい」「たしかに細かい」

# 同サイトより
Cross-Origin-Opener-Policy: same-origin-allow-popups
# 同サイトより
Cross-Origin-Embedder-Policy: require-corp

CORSはよく聞くヤツですね」「知ってるものが出てきた」「ちなみにCORSのヘッダーは、ない状態が最もセキュア」

# 同サイトより
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

参考: Rails アプリケーションのセキュリティ対策(CORS/CSP/HSTS)

「こうしたセキュリティ関連ヘッダーは適切に設定すべきですね: 特にSPAは1つのページ内であらゆるデータを読み書きするようになるので、一箇所でも不備があると他の部分にも影響しがち」「たしかに」「セキュリティヘッダーのリファレンスとして便利そうなサイト👍」「ヘッダーが多すぎないのが嬉しいです😂」

参考: シングルページアプリケーション - Wikipedia — SPA

🔗 Priority Hintsによるリソース読み込み最適化


つっつきボイス:「Priority HintsはWebページ内の要素の読み込みで優先度を指定できる新しめの仕様ですね」「以下の記事は2018年の時点でPriority Hintsをチェックしていました↓」

「お〜、Blink(Chromeなどで使われているレンダリングエンジン)ではこれらに優先順位を設定できるのね↓」「『Priority Hintsはヒントであってディレクティブ(指示)ではない』、なるほど」

参考: Blink (レンダリングエンジン) - Wikipedia


同記事より

「具体的には以下のようにタグでimportance="low"のように指定する↓と、ブラウザ側で優先順位を割り当てる」「"low""high""auto"の3つか」「画像のimgにも指定できるんですね」「その場合CSSで画像サイズをきちんと指定しておく方がいいかも」

<!-- 同記事より -->
<!-- include trial token in the <head> -->
<meta http-equiv="origin-trial" content="{Replace with origin trial token}">

<!-- Lower the priority of script file -->
<script src="script.js" importance="low"></script>

<!-- Alter the priority of images -->
<img src="Background.jpg" width="400" importance="low">
<img src="Sunset.jpg" width="400" importance="high">

<!-- Note that importance="auto" is the default based on the spec if not specified -->
<img src="Flower.jpg">

「優先順位の仕様↓は定められているけど、細部の解釈はブラウザ依存になる可能性があるかもしれませんね」「あ〜たしかに」


同記事より(一部)

importanceを全部Highにしたりするのはダメなのかな?」「無意味だと思いますよ😆 : 上の仕様の上下矢印などを見た感じでは、仮に全部Highにしたとしても優先順位は同じにならないでしょうね」「あ、たとえばHighに下向き矢印がある項目は、それより低くなる可能性があるということなんですね」

「Priority Hints指定なし(左)とあり(右)では以下のように変わるんですね↓」「わかりやすい〜」

「優先順位をここまで追い込んで使うことはすぐにはないかもしれないけど、importance="high"asyncを指定する↓のは効果高そうな感じなので、これなら書いてもいいかなと思いました」

<!-- 同記事より -->
<script src="async_but_important.js" async importance="high"></script>

🔗言語/ツール/OS/CPU

🔗 Crontab.guru


つっつきボイス:「なるほど、crontabのスケジューリングの設定を支援するサイトですか」「これ面白いですね」「たしかGitHubのドキュメントでこのCrontab.guruが参考としてリンクされてたのを見たことがありますよ」

参考: crontab - Wikipedia

後で見つけました。

crontab guru を使うと、クーロン構文の生成および実行時間の確認に役立ちます。 また、クーロン構文の生成を支援するため、crontab guru のサンプルリストもあります。
ワークフローをトリガーするイベント - GitHub Docsよりより

🔗 crontabの罠

「ところでcrontab形式って、実は標準というものがないんですよ」「え?」「そうなんです😢」

「たとえば、Linuxだと曜日は日曜始まりで0-6が割り当てられていて、さらに7も利用可能なので、07が日曜日になる: これなら7で割った余りで曜日を出すみたいな処理がやりやすい」「なるほど!」

参考: crontab 曜日設定などメモ - Qiita

「でもAmazon EventBridge↓(旧Amazon CloudWatch Events)のCrontab形式はかなり特殊で、曜日が日曜始まりの1-7になってる」「え〜それヤバいじゃないですか!」「きっとハマる自信ある」「誰もが一度はハマります」

参考: ルールのスケジュール式 - Amazon CloudWatch Events

「さらに厄介なのは、EventBridgeではcrontabで指定できる時刻がUTCのみという点」「え〜!JSTとかで書けないんですか?」「ローカルタイムが指定できないので、時刻を指定するたびに変換してあげないといけません」「ややこしい…」

参考: 協定世界時(UTC) - Wikipedia

「ちなみにLinuxのcrontabだとTZ=タイムゾーン名でローカルタイムを指定できます↓(指定し忘れると悲惨ですが)」「そういえばそうですね」「Linuxのcrontabに慣れているほどAWSでハマりがち」

参考: cron - How do you set the timezone for crontab? - Ask Ubuntu

「ところが面白いことに、AWSのマネージメントコンソール経由だとEventBridgeでローカルタイムを指定できるんですよ(↓証拠写真)」「へ〜!」「これについてさんざん調べたんですが、APIレベルではできない😢」「残念…」

「そういったわけで、crontab周りはクラウドの設定をレビューするときの要チェックポイントです」


後編は以上です。

バックナンバー(2021年度第4四半期)

週刊Railsウォッチ: insert_allやupsert_allのタイムスタンプ自動更新、rails/contextsにロジックを置くほか(20211025前編)

今週の主なニュースソース

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

StatusCode Weekly

statuscode_weekly_banner


CONTACT

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