Slide 1

Slide 1 text

Kanazawa.rbのLT大会を 支える技術の裏側を変更する Ruby on Rails + Litestream 編 2025/01/18 北陸三県.rb Lightning Talks in Kanazawa@ ITBP武蔵 Kanazawa.rb muryoimpl

Slide 2

Slide 2 text

Kanazawa.rb の LT 大会は Slack の Slash Command である KZLT コマンドでエントリと発表順の 管理をしている

Slide 3

Slide 3 text

実行の仕組み Slack Apps Script /kzlt を入力 POST リクエスト Webアプリとして公開された Apps Script end- point レスポンス Spread sheet 結果を 書き込む doPost() 関数 hook で呼び出す ※動かすためにお金はかけていない

Slide 4

Slide 4 text

KZLT に対する不満 ● Spreadsheet が裏側だと同時に同セルに書き込みすることがあり、 エントリが消されてしまう(頑張らずにあえて放置してた) ○ 創造主による監視、修正が必要 ● データを扱う際は、 SQL を使いたい ○ Spreadsheet を全部舐めてデータ集計を頑張りたくない ● 慣れた言語を使って実装したい ○ Kanazawa. “rb” だし ● 無料 もしくは 使った分だけお支払いにしたい ○ == 使わないときはお金かからないようにしたい

Slide 5

Slide 5 text

年末年始を使って 作り変えちゃおうか と啓示があったので 作り変える

Slide 6

Slide 6 text

どう作るか? ● SQLite + Litestream を採用する ○ SQLを使いつつ、DB をファイルとして扱いバックアップをとることで常時動く Database にかかるコス トをなくす ○ entryの登録はDBへのINSERTが基本になるので、書き込み時に衝突して消えることはなくなるはず ● Ruby on Rails を採用し、 Cloud Run 上で動かす ○ リクエストをさばく分だけ課金されるようにする。おそらく無料枠で足りるだろう ○ 慣れ親しんだ言語、慣れ親しんだフレームワークを使う ○ コンテナ を作り、その中で Litestream を動かす ● Google Cloud 上の Cloud Run でアプリを、 Cloud Storage で SQLite を管理する ○ https://github.com/fractaledmind/litestream-ruby を Rails と一緒に使って Cloud Storage を保 管先にする ● https://github.com/muryoimpl/kzlt-ruby にコードを置く

Slide 7

Slide 7 text

注意点 ● SQLiteを Litestream で使うには WAL を有効にする必要がある ○ Write-Ahead Logging オプションのこと ○ 有効にすると高速化し同時実行性が高まるらしい ■ https://www.sqlite.org/wal.html ○ その他チューニングは PRAGMA、cofig/database.yml と patch で 適用する ○ patchとその記事: https://fractaledmind.github.io/2023/09/07/enhancing-rails-sqlite-fine-tuning/ ● litestream-ruby に付属の puma extension を有効にする ○ pumaの扱うイベントに replicateを任せるなら puma.rbに追記が必要。今回は任せる ○ https://github.com/fractaledmind/litestream-ruby?tab=readme-ov-file#replication

Slide 8

Slide 8 text

ということで KZLT の裏側を 新しいものに差し替えた

Slide 9

Slide 9 text

新しい仕組み Slack /kzlt を入力 POST リクエスト Google Cloud Cloud Run レスポンス データを 世代管理 Cloud Storage bucket generations generations generations Container Ruby on Rails Litestream ● Cloud Build で GitHub と連携し、自動でコンテナをビルドしている ● Artifact Registryサイズ超過で今月は数十円かかるが、設定で解決する見込み

Slide 10

Slide 10 text

モデル この 4 モデルで管理する。 workspace のデータは data_migrate で入れる。 他の workspace から request がきても処理しない つくりになっている。

Slide 11

Slide 11 text

やったこと ● rails new して、Gemfile に `gem “litestream”` を追記する ● bundle install して、 `rails g litestream:install` を実行する ● config/litestream.yml に、保存する bucket, path, type: gcs, を記述する ● Dockerfile に litestream のインストール処理を記述する ● Dockerfile の CMD に 、entrypoint.sh を指定する ○ 古い sqlite3 ファイルを削除する ○ rails litestream:restore – –if-replica-exists を実行し、 sqlite3ファイルを復元する ○ rails server を実行する ● config/puma.rb に production のときだけ宣言 plugins :litestream を実行する ように設定する ● sqlite に pragma を適用する patches を当てる ● リクエストを処理して希望のコマンドに当たる処理を実装する

Slide 12

Slide 12 text

Litestream を使うと ←↑のようにCloud Storage 上に SQLite が世代管理される

Slide 13

Slide 13 text

置き換えてよかった点 ● いつもの言語 Ruby で実装 & データの操作は SQL (ActiveRecord) でできるよう になった ○ セルの操作よりは断然イメージしやすく実装しやすい ● ひきつづき、低コストで運用できる ○ リクエスト毎の課金だが、無料枠がありこれを超えることはなさそう ○ コンテナイメージの管理がサイズ課金だが、削除ポリシー適用であっても数円になる予定 ○ 仮にCloud Run を起動しっぱなしにしても、年 2 回なら大したコストではなさげ ● Strategy Pattern や Command Pattern な感じの実装で適度に分割統治できた 気がする ○ サブコマンドの追加が容易になった

Slide 14

Slide 14 text

ちょっと悪くなった点 ● Cloud Run なので、コンテナの停止 → 起動までに時間がかかるようになった ○ 初回リクエストからコマンドを受け付けるまでの間、エラーになっちゃう ○ 暖機運転的なリクエストをあらかじめしておくか? ○ 年 2 回運用ならその日だけ常時動かしておくのもいいかな、とは思う ● フレームワーク、ライブラリを使うようになったので保守が必要 ○ dependabot PR のマージが基本だとは思うが、 runtimeの更新やライブラリの breaking change が出る可能性はある ● Litestream を使っている関係で、スケールアウトはできない ○ それほど Kanazawa.rb の LT 大会に参加する人が増えるというのは、嬉しい悲鳴の範疇なので は? ○ そうなったらちゃんとした hosted database を使おうと思う

Slide 15

Slide 15 text

まとめ ● Cloud Run + Litestream でお安く動作環境を準備できた ● Ruby + Ruby on Rails の慣れた環境、 SQLでデータを操作できるようになった ● コマンド毎に処理を実装できるようになったので、追加・修正は簡単になった ● 初回起動に時間かかるは運用で回避する。保守に手間がかかるは毎月の meetup でやればどうということはないかな ● SQLite利用 + 同時実効性上昇の設定で、書き込みでエントリが衝突、消える問 題は解消されたはず

Slide 16

Slide 16 text

参照URLs ● https://litestream.io/ ● https://github.com/fractaledmind/litestream-ruby ● https://fractaledmind.github.io/2023/09/07/enhancing-rails-sqlite-fine-tuning/ ● https://github.com/fractaledmind/litestream-ruby?tab=readme-ov-file#replication ● https://github.com/muryoimpl/kzlt-ruby