「重複は実質ゼロ」と数えたのに、監査は112組を出していた
トレカダッシュ 開発の記録 / 2026年10月
iOS アプリ「トレカダッシュ」には、同じ商品が複数の商品として登録されてしまう「重複」を、毎晩、統合する処理があります。ある日、自分で数えて、「重複は実質ゼロ」と記録しました。ところが、リポジトリの監査は、112 組を出していました。自分の測り方が、間違っていたのです。コミットの記録で、経緯を書きます。
このサイトには、トレカダッシュの作品ページはまだありません。ここに書くのは、開発の記録です。
「ゼロ」と数えて、112 組が出た
112 組の実体を見ると、たとえば、ヴァイスシュヴァルツの「ブースターパック ラブライブ!サンシャイン!!」が、7 件に割れて登録されていました。統合の処理が、毎晩動いているはずなのに、です。
原因:毎晩、途中で時間切れになっていた
統合の処理は、全ジャンルを通すと、約 15 分かかります。ところが、毎晩の定期実行に与えている持ち時間は、480 秒(8 分)でした。順番は、毎回、同じジャンル(ポケモン)から始まります。つまり、毎晩、ポケモンの途中で時間切れになり、後ろのジャンルには、永久に届かなかったのです。
数えたときに「ゼロ」だったのは、見ていた範囲(先頭のジャンル)だけが、きれいだったからでした。
直し方
- 持ち回りにする。前回の続きのジャンルから始めて、時間予算(6 分)が尽きたら、止めます。次の晩は、止まったところから続きます。
- まず、手で完走させる。全ジャンルを手で最後まで流すと、重複は 112 組から 0 組に、商品は 2,753 件から 2,570 件になりました。
その前に分かっていたこと:1 回では終わらない
この 2 日前(9 月 5 日)にも、統合について、わかったことがありました。A を B に統合すると、B の名前が、別の C と同じになることがあります。すると、1 回では終わりません。実データでは、こうでした。
| 回 | 統合した件数 | その結果 |
|---|---|---|
| 1 回目 | 138 | 新たに 53 組の同名が発生 |
| 2 回目 | 54 | 同名の重複は 0 組 |
商品は 2,935 件から 2,713 件になりました。そこで、毎日の枠では、統合が 0 件になるまで繰り返す(上限 3 回)ようにしました。今回の「時間切れ」は、この繰り返しの、さらに手前の問題でした。
同じ日に、ほかにも三つ
- 受付中の抽選 6 件が、別の商品の定価で、消えていた。7,200 円(公式の 360 円 × 20 パック)の抽選が、記事に残っていた別の商品の定価 27,500 円と比べられて、価格で却下されていました。直す条件に、「証明できるときだけ直す」を足しました。実データの全件で、条件に合うのは 10 件で、全部が正規の価格の販売でした。11 件を、表示に戻しています。
- 突き合わせの誤報。「記事はあるのに非表示」の 17 件のうち、9 件は、同じ店の別の書き方で、代わりの記事が表示されていました(「千歳鳥山店」と「千歳烏山店」のように)。代わりが表示中なら、カバー済みと数えるようにして、カバー率は 87% から 90% に、非表示は 17 件から 4 件になりました。
- 監査のほうが、止まっていた。監査用の読み取りの部品が、
=>のすぐ後ろにある正規表現を、割り算と読み違えて、監査 4 本が、ReferenceErrorで落ちていました。切り出せなかった名前を、黙って飛ばさず、理由を出すように直しています。
分かったこと
「ゼロ」と数えたら、まず、何を数えたかを疑う。
- 見た範囲が、全体とは限らない。毎晩、先頭のジャンルだけが処理されていたので、先頭だけを数えれば、きれいに見えます。
- 時間に制限のある処理は、「終わったか」を見る。動いていることと、最後まで届いていることは、別です。
- 数える道具も、壊れる。監査が止まっているときは、結果が「0 件」に見えます。止まっていることに、気づく仕組みが要ります。
この記事は、コミット(2026年9月5日、9月7日)の記録から書きました。
この話に出てくるもの
- 「取れた」と読んでいたのは、ただの案内ページだった — 同じ日の、別の記録
- 「9種セット」の正体は御三家9商品だった — 同じアプリの、突き合わせの記録
ほかの記録
- 「9種セット」を中身ごとに分けて、偽の商品が80個できていた — ポケモンカードの9種セットは1つの商品なのに、中身ごとに分けて、実在しない商品が80個できていた。入口を止め、親22件を戻し、子190件を外し、偽の商品を消した記録。
- 「9種セット」の正体は御三家9商品だった:同じ商品なのに、決して一致しなかった — 他のまとめサイトと突き合わせたら、抽選の表示は54%だった。商品の取り違え、比べ方の左右非対称、記事IDの穴。カバー率を91%にした記録。
- 「取れた」と読んでいたのは、ただの案内ページだった:3日間、商品が0件 — ポケモンセンターの取得が3日間ずっと商品0件だった。安い設定が返した2,410バイトの「JavaScriptを有効に」ページを、成功と読んでいた。判定を1か所に集めた記録。
コメント
感想や、記事の間違いの指摘は、ここへ。書くには、GitHub のアカウントが要ります。
押すと、giscus(giscus.app)と GitHub に接続します。押さなければ、接続しません。詳しくはあつかいに書いています。