かつてBOOTHのライブラリは、自分が購入した商品を並べるシンプルな世界でした。そんな世界に<購入せず、所有ができる>ギフトという概念が生まれ、シンプルだった世界は終焉を迎えます。BOOTHのギフト機能実装の際にハマったActiveRecordの落とし穴とその解決策の話です。
pixiv Inc.限界ORM!BOOTHとギフトとライブラリRND
View Slide
ProfileRNDエンジニアクリエイター事業部 BOOTH部所属絵と漫画を描く が趣味RND(らんど)と読みます
前提知識検索する時に自動でクエリを組み立ててくれる心づよい友達ORM (= Object Relation Mapping)RDB レコードとオブジェクトとを変換する技術ActiveRecord: Rails ORMフレームワーク
今回 話
BOOTH ギフト機能 なしクリエイターとファンを繋ぐC2C 販売プラットフォームRailsで書かれている今年10周年BOOTH
2022年12月
DL商品を購入するギフト用URLが発行されるURLにアクセスすると他 人がDL商品を受け取ることができる
こ 機能
実装が大変だった
これまで BOOTH所有者 = 購入者注文 LineItem注文と商品 関連テーブル商品購入者(所有者)*所有**これが...注文完了かつ、LineItemがあれ 所有してる
ギフト 場合所有者 ≠ 購入者注文 LineItem注文と商品 関連テーブル商品購入者 *所有(ギフトじゃない時)**ギフト受取ユーザー所有(ギフト 時)
ということ所有=購入で運用されてきたサービス所有と購入を分離、影響箇所 ...注文LineItem注文と商品 関連テーブル商品購入者発送売り上げ管理カートpixivFACTORYと連携送り状(伝票)生成レコメンドアルゴリズム無限にある
ということ所有=購入で運用されてきたサービス所有と購入を分離、影響箇所 ...注文LineItem注文と商品 関連テーブル商品購入者発送売り上げ管理カートpixivFACTORYと連携送り状(伝票)生成レコメンドアルゴリズム無限にあるit’s 無理
やった意外となんとかなる必要な 気合いやったらできたgrepして出てきた箇所をnotionに書き出して影響 有無を判断
本題
ライブラリ なし
ライブラリギフトによって所有 経路が2種類になった所有している商品が入手順に並ぶページ
ギフトで受け取った商品も自分で買った商品もライブラリに入手順で並べる
2種類 経路でJOINされたテーブルを結合でもRails(ActiveRecord)にないunionを実装したgem?もしく 生SQLを書くか、orメソッドなどで頑張るUNIONが必要そう
分けたらええやん「無理そう」な設計が出たら要件を見直す別ページに分けて解決、ユーザーも困らない。ギフトで受け取った商品別ページに遷移して表示
まだある
ギフト、何回でも受け取れるこんなケースこ 前言ってたアバター、プレゼントで送ります好きそうなアバターあったんでギフトで送りますダブってしまったけど受け取らない も申し訳ないなぁ...
受け取れます
何回でも
ということ
ライブラリ複数回受け取った商品最新 1件だけ表示される所有している商品が入手順に並ぶページnew!
複数回受け取った場合GROUP BY `商品`1件にまとめて表示ORDER BY `ギフト.受け取り日時` DESC最近受け取ったも が先にくるように並べる
こうか??
ダメORDER BY GROUP BY より後に実行される
欲しいクエリ これActiveRecordで記述する手段 ない、一部生SQLになる
別 案: サブクエリ件数がめちゃくちゃ増えてくるとパフォーマンスが悪くなるActiveRecord from を使うとサブクエリが使える
もっと良さそうな案変えようぜ、テーブル設計所有を表現するテーブルを用意アプリケーションで整合性を保つ移行する 大変だがシンプルで変更につよそう
すまんがリリースまで時間ないわ実装する に時間がかかる今回 サブクエリ案で年内にリリース。ユーザーに素早く価値を提供することが大事
まとめ:教訓ActiveRecord、なんかすぐ限界になりがち限界が見えたら1. まず要件と仕様を見直す。 コードを書かずに解決しよう2. テーブル設計を見直す。 プロダクトをシンプルに保とう3. ActiveRecord芸を頑張ったり、生SQLもありかも(ユニットテストがしっかり書かれててCIでテストがちゃんと動いてるなら生SQLで別にいいんじゃないか(小声))
早くこれにしたい で、エンジニアを募集中ご清聴ありがとうございました