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

週刊Railsウォッチ: Bundler自身のバージョンロック機能、gem署名メカニズムの提案ほか(20220216後編)

こんにちは、hachi8833です。

週刊Railsウォッチについて

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

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

🔗Ruby

🔗 提案: gemに署名するメカニズム(Ruby Weeklyより)


つっつきボイス:「Shopifyの記事です」「お、gemに署名を付けやすくするしくみについての提案のようですね」「なるほど」「gemへの署名を何らかの形で自動化しないとgem作者がつらくなるからでしょうね」「署名の手間を軽減する提案なんですね」「gemに邪悪なコードを入れられてしまう問題はときどき起きるので、gemへの署名はたしかに必要: この間のrubygems.orgのAPIキー発行の改良もその流れの一環かもしれませんね(ウォッチ20220209)」

「記事が長いので流し読みの範囲ですが、たとえばトークンを適切な時期に失効させる議論もしていそう」「その辺大事そうですね」「有効期限が長過ぎるトークンはそれ自体セキュリティ上よくないので」

🔗 二要素認証アプリよもやま

「ところで話は変わるんですが、この間iPhoneをやむを得ず初期化したときに、Google Authenticatorアプリに登録した二要素認証の設定が飛んでしまって、他の二要素認証は手動で復元したものの、Rubygems.orgの二要素認証の復元方法が見当たらなくて、ruby-jp Slackで教えていただいたサポートのメアドに今問い合わせているところです😢」「ありゃ〜それは大変そう」「リカバリーキーは持っているのでログインはできるんですが、二要素認証を解除する画面でワンタイムパスワードを求められてしまいました」

「そうならないためにはクラウド上に設定を保存できる二要素認証アプリを使うのが確実でしょうね」「はい、Rubygems.orgのヘルプページにもそういうアプリの方がいいよと注意書きがありました😅」「Google Authenticatorのように特定デバイスのみで使える二要素認証の方がたしかにセキュアですけど、デバイスを紛失したり使えなくなったときが痛い」「たしかに」

「ちなみに1Passwordには二要素認証機能もありますよ」「え、自分も1Passwordの有料ユーザーですけどそんな機能が入っているんですか?自分もそうしようかな...🤔」

参考: 家族、ビジネス、チームのためのパスワード管理ツール | 1Password


追いかけボイス:

ごもっともでした🙏。Rubygems.orgで紹介されていたAuthyやAuthenticator Plusなどのクラウドにデータを置く二要素認証アプリを検討してみることにします。

参考: 「Twilio Authy」をApp Storeで
参考: Authenticator Plus


その後Rubygems.orgのサポートから連絡をいただき、二要素認証を復元できました🙇。リカバリーキーをワンタイムパスワードの欄に入力するのがポイントでした。

参考: Setting up multi-factor authentication - RubyGems Guides

🔗 RubyコードのWasmをブラウザ実行するのに1日かからなかった(Ruby Weeklyより)


つっつきボイス:「RubyをWasmとブラウザで動かす記事だそうです」「他のスクリプト言語の詳しい事情はわかりませんが、少なくともRubyは多くの基本機能が本体に入っているので、こういうときに外部gemを追加しなくてもかなりのことができるのがいいですよね」

🔗 依存関係の混乱による脆弱性と戦う(Ruby Weeklyより)


つっつきボイス:「これもShopifyの記事で、600以上のアプリで依存関係の混乱による脆弱性を解決したそうです」「Shopify頑張ってる」「Bundlerでの依存関係の混乱ってこういう感じのヤツか↓」「こういうのって自分で見ていてもわからなくなりがち」「このgemとこのgemが特定バージョンの組み合わせでインストールできなくなったりすることってたまにありますよね」

# 同記事より: 新しいバージョン
GEM
  remote: https://example.com
  specs:
    private_gem (1.8.0)
      dependency_1
      dependency_2 (>= 2.7, < 4)

GEM
  remote: https://rubygems.org/
  specs:
    public_gem (6.1.4)
      dependency_1
# 同記事より: 古いバージョン
GEM
  remote: https://example.com
  remote: https://rubygems.org/
    specs:
       private_gem (1.8.0)
         dependency_1
         dependency_2 (>= 2.7, < 4)
       public_gem (6.1.4)
         dependency_1

「普段のBundlerは何も考えずに楽に使えますけど、ひとたび問題が起きるとトラブルシューティングで手間取りがち」「そうそう」「古いRailsプロジェクトで起きがちなのも大変...」「ちょうど次の記事もBundler関連です」

🔗 Bundler v2.3でBundler自身のバージョンがロックされるようになった(Ruby Weeklyより)


つっつきボイス:「Bundler v2.3からBundler自身のバージョンをロックするようになったそうです」「今までは該当バージョンのBundlerがなかったときは最新バージョンにフォールバックしていたのが、v2.3からはBUNDLED WITHのバージョンどおりのBundlerを使うようになったのね」


「Bundlerはある時期からGemfile.lockの末尾にBUNDLED WITHを追加するようになりましたけど↓、メンバーの誰かが不用意にローカルでbundle installしたものをコミットしたりするとCIが止まったりすることがありましたね」「あ〜そうそう」「あれはマジでつらい😢」

# Gemfile.lockの末尾の例
RUBY VERSION
   ruby 3.1.0p0

BUNDLED WITH
   2.3.5

「この問題が起きるとBundlerが期待どおりに動かなくなるので、BUNDLED WITHを取り入れるなら互換性を失わない形にして欲しかったとよく思ったものです」「今の自分の環境でBundlerがうまく動かないのってもしかするとこの辺の問題なのかも...」

「BundlerがRuby本体に取り入れられてgem install bundlerしなくてよくなってからはあまり起きなくなりましたけど、それまではメンバーごとにBundlerのバージョンが合っていない可能性がちょくちょくあった」「そんな時代もありましたね」「それでも個別にBundlerを手動でインストールすると起きたりしますけどね: レビューで気づけばいいけど見逃すとCIが死ぬ」

🔗 その他Ruby


つっつきボイス:「最近流行りのWordleをRubyで解いてみたそうです」「英語圏でどえらく流行してますよね」「まだ遊んでないけど」「自分も」

参考: Wordle - The New York Times

「Wordleはノリ的には女神転生のコードブレイカーっぽいかも」「リモートワーク流行りのおかげで盛り上がってるのかもしれませんね」

参考: コードブレイカー - 真・女神転生IMAGINE攻略Wiki
参考: code breakerの意味・使い方・読み方 | Weblio英和辞書 -- code breakerは推理小説のジャンルでもあるようです


「ついでにゲームの話をすると、最近のイベントで見たこのGeoGuessrというゲームを集団で解く動画がものすごかった↓」

参考: GeoGuessr | AGDQ2022 - Twitch

「ジオゲッサーという名前からして、Googleマップのストリートビューを見て場所を当てるとか?」「そうそうそんな感じ: 推測した場所を地図上でクリックして正解の場所と距離が近いほど高得点になる」「お〜なるほど」「最初のうちはエッフェル塔みたいなわかりやすい名所ですけど、だんだんどこの山だか砂漠だかわからないような場所に放り出される」「うまいところに目を付けたゲームですね」「元の動画は英語ですけど日本語で解説されてます」

🔗DB

🔗 mini_sql: 最小限のSQLエグゼキュータ(Ruby Weeklyより)

discourse/mini_sql - GitHub


つっつきボイス:「Discourseのgemだそうです」「PostgreSQLとSQLiteのインターフェイスを持つ、よくある感じのシンプルなクエリエグゼキュータのようですね: プレースホルダ機能や、クエリ結果をeachで回すみたいなことができるらしい↓」「デコレータを足してRubyっぽく書けるんですね」

# 同リポジトリより
pg_conn = PG.connect(db_name: 'my_db')
conn = MiniSql::Connection.get(pg_conn)

puts conn.exec('update table set column = 1 where id in (1,2)')
# returns 2 if 2 rows changed

conn.query("select 1 id, 'bob' name").each do |user|
  puts user.name # bob
  puts user.id # 1
end

# extend result objects with additional method
module ProductDecorator
  def amount_price
    price * quantity
  end
end

conn.query_decorator(ProductDecorator, "select 20 price, 3 quantity").each do |user|
  puts user.amount_price # 60
end

p conn.query_single('select 1 union select 2')
# [1,2]

p conn.query_hash('select 1 as a, 2 as b union select 3, 4')
# [{"a" => 1, "b"=> 1},{"a" => 3, "b" => 4}

p conn.query_array("select 1 as a, '2' as b union select 3, 'e'")
# [[1, '2'], [3, 'e']]

p conn.query_array("select 1 as a, '2' as b union select 3, 'e'").to_h
# {1 => '2', 3 => 'e'}

「mini_sqlは昔にさかのぼったかのようなデータベースコネクションライブラリという感じかな」「そういえばRuby Weeklyではsafeと紹介されていました」「どれどれ、mini_sqlは毎回できるだけ結果セットをクリアするからmemory bloatしにくいというのがsafeということみたい」「あ、そういうことですか」「ちなみに、一般的にアプリケーション側のメモリ効率としては、結果セットを一気に全部取り出すよりSQLのカーソルで取り出す方が有利」

参考: Ruby's external malloc problem

「mini_sqlはおそらくeachで結果セットを取り出すたびに結果セットをクリアするんじゃないかな: lib/の下のコードを見てみるとquery_eachで毎回result.clearを呼んでいる↓」「なるほど、こまめに片付けてmemory bloatを避けているんですね」「GCに任せてもいいんですが、GCされるまではメモリに乗り続けるので、明示的にクリアする方が片付くのは早いでしょうね」

# https://github.com/discourse/mini_sql/blob/main/lib/mini_sql/postgres/connection.rb#L106
      def query_each(sql, *params)
        raise StandardError, "Please supply a block when calling query_each" if !block_given?
        if params && params.length > 0
          sql = param_encoder.encode(sql, *params)
        end

        raw_connection.send_query(sql)
        raw_connection.set_single_row_mode

        loop do
          result = raw_connection.get_result
          break if !result

          result.check

          if result.ntuples == 0
            # skip, this happens at the end when we get totals
          else
            materializer ||= deserializer_cache.materializer(result)
            result.type_map = type_map
            i = 0
            # technically we should only get 1 row here
            # but protect against future batching changes
            while i < result.ntuples
              yield materializer.materialize(result, i)
              i += 1
            end
          end

          result.clear
        end
      end

「mini_sqlはどんなときに使えるんでしょうか?」「少なくともActive Recordの代わりに使うものではないと思いますが、プレースホルダのような最小限の機能は備わっているので十分コードは書けますね: 十数年前のPHPでもmysqli_fetch_assocとかでこんな感じでコードを書いてましたよ」「あ〜、PHPerだったので今のですべて理解できました、あのノリですね」

参考: PHP: mysqli_result::fetch_assoc - Manual

「毎回メモリをクリアするということは効率は高い代わりに当然速度が犠牲になるので、mini_sqlが合うかどうかは用途次第ということになるんでしょうね」「そうそう、ものすごく巨大なデータセットから取り出したいときとか、メモリが潤沢でない環境で使いたいとか」

「Railsはメモリが潤沢な環境が前提なので、極端なことをしない限りそうそうスラッシングしませんけど、たとえばAWS Lambdaのようにメモリが限られたFaaS的環境で巨大なデータセットからちょっぴり取り出したいときだったら、mini_sqlのようにこまめにクリアするアプローチが合うかも👍」「なるほど」「型変換とかはできないので、そういう機能が豊富なActive Recordとはあり方からして違うでしょうね」

参考: スラッシング - Wikipedia

🔗クラウド/コンテナ/インフラ/Serverless

🔗 Google CloudでサーバーレスSparkが一般公開(Serverless Statusより)


同記事より


つっつきボイス:「お、Sparkだ」「GoogleのBigQueryからも使えるようになるんですって(現時点では非公開プレビュー)」「Sparkって何でしたっけ?」「Apache Projectのひとつであるオープンソースの分散フレームワークですね」「言われてみればApacheのサイトでロゴを見たことあったかも」「そのSparkをサーバーレスで使えるようになったのか」

参考: Apache Spark™ - Unified Engine for large-scale data analytics
参考: Apache Sparkとは何か――使い方や基礎知識を徹底解説:Amazon EMRで構築するApache Spark超入門(1)(1/3 ページ) - @IT

「SparkはHadoopのお仲間的な感じ」「HadoopはたしかHDFSが元になっていましたね」

参考: 分散処理技術「Hadoop」とは:NTTデータのHadoopソリューション
参考: HDFS(Hadoop Distributed File System) とは | 技術関連用語集 | BBTowerレポート | 株式会社ブロードバンドタワー

「AWS S3はHDFSでもあるそうなので、EMRでHDFSを使いたいときはS3に置けばいいというのが魅力的だなと思いました: S3にJSONとかを置いたらHadoopが読み込んでくれるようにできる」「HadoopのストレージをS3で代替できる?」「はいそんな感じです: AWSでHadoopを使いたければECS上にHDFSのクラスタを構築しないといけないのかなと思ってたら、それS3でできるよということでした」「へ〜」

参考: Amazon EMR(Hadoopなどのビッグデータフレームワークを簡単に実行)| AWS

「言われてみればS3には当初からHDFSがあったかも」「そうそう、ありましたね」「S3の中身はHDFSとかなり違いそうな気もしますけど、オーバーレイネットワーク上でマルチノードをまたがる単一のファイルシステムを構築するという意味では、S3とHDFSがやりたいことはそんなに遠くないかも」「中身は違ってそうですけどそんな感じですね: Sparkはそれをメモリ上に構築するヤツです」「ははぁなるほど」

「サーバーレスのSparkってペタバイト級のメモリでも使えるのかな?」「Googleならやれそうな気もしますけどね: お金次第でしょうけど」

🔗 GCPとAWS

「何度か話していますが、GCPのあり方はAWSといろいろ違うので使う側の学び方も違ってきますよね: AWSは責任共有モデルで、基本的にコンピュテーションパワーやインフラやAPIの部分だけを提供して、その上で何をするかは自由だけど責任もユーザー側にある、FaaS的なサービスもランタイムまでは用意するけど運用やメモリ管理などはユーザーに委ねるというスタンス」「そうそう」

参考: 責任共有モデル | AWS

「GCPの印象は、Googleのサポートがアプリケーションレイヤまで及んでいる感じで、むしろアプリケーションライブラリ的な側面を感じる」「わかります」「アプリケーションエンジニアとしては、GCPにどっぷり浸かる方がいろいろ便利に使えるのかもしれませんね」

「その分GCPはアプリケーションライブラリのドキュメントをみっちり読まないといけないんですが」「それそれ!ドキュメントをもうちょっと親切に書いて欲しいです😢」

「逆にAWSはLinuxの知識があれば基本的にやれますよね(AWS自体の知識を別にすれば)」「ほんとそう😆」「AWSはLinuxの知識と経験がそのまま通用するし新サービスの概要もつかみやすいけど、GCPの場合はまずサービスのパラダイムから確認しないといけない感じ」「そこなんですよ」「結果セットが1000件以上のときはこっちのメソッドを使うこと、みたいなのをGCPで見かけたりしますね」

🔗言語/ツール/OS/CPU

🔗 IntelがRISC-Vに大規模投資


つっつきボイス:「今さらだけどRISC-Vってリスクファイブって読むんですね」「RISC-Vはオープンソースの命令セットアーキテクチャ(ISA)」「Intelがそこにドカンと投資したのか」(しばしItaniumなどの話題)

参考: RISC-V - Wikipedia

「ツイートにもありますけど、量販店で売られているような民生用機器の組み込み系で最近RISC-Vが続々使われ始めているのが自分的にとてもアツい」「たしかにワイヤレスイヤフォンとかもろ民生用ですね」「そうなるとARMの組み込み市場と完全に競合するので、ARMや日本のルネサスあたりが今後どうなるかも含めて気になっています」「黒船感ありますね」

参考: ARMアーキテクチャ - Wikipedia
参考: ルネサスエレクトロニクス - Wikipedia


後編は以上です。

バックナンバー(2022年度第1四半期)

週刊Railsウォッチ: Rails 7.0.2の改修内容、receipts gemでレシートを作成ほか(20220214前編)

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

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

Ruby Weekly

Serverless Status

serverless_status_banner


CONTACT

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