監査 61 本を総点検して見つけた 4 つ:朝 4 時に 51 本が固まり、鍵の期限は 55 秒で、定価の補完は「入れない」と決めた
トレカダッシュ 開発の記録 / 2026年9月
iOS アプリ「トレカダッシュ」の裏側には、異常を見つける監査が 61 本あります。2026 年 9 月 8 日の未明、その全部を流して、0 件ではなかった項目を、1 つずつ実データで確かめる作業をしました。
この記事は、そこで見つけた 4 つの話です。3 つは「直した」話で、1 つは「測ったうえで、あえて入れなかった」話です。
数字は、2026 年 9 月 7 日夕方〜8 日朝の作業の記録から書いています。
1. 1 日 1 回の処理 51 本が、朝 4〜5 時に固まっていた
朝 4 時 53 分の実測は、こうでした。
- 同時実行の枠 14 が、いっぱいに張り付いている。待ちが 8。
- 6 本の処理が、上限の 540 秒でタイムアウトしている。
- 守りたい「瞬殺監視」と「Amazon の最速枠」が、1 時間に 9 回ずつ見送られている。
原因は、時刻の偏りでした。1 日 1 回の処理を数えると、4 時に 27 本、5 時に 24 本。一方、1 時と、10 時から 21 時までは、0 本でした。
直し方は、1 本ずつ時刻を書き換えることではありません。後から足した処理には、効かなくなるからです。時刻をずらす幅の仕組みそのものを直しました。ずらす幅が、一律 270 秒だったのを、間隔が 6 時間以上の処理は、最大 1,800 秒(30 分)まで散らします。27 本を 30 分に散らすと、約 67 秒おきになり、同時に走るのは 3〜5 本です。
30 分に留めたのは、次の時刻の枠にはみ出さないためです。「2 時に点検して、3 時に補完する」のような、時刻による順番を、壊したくありませんでした。
2. 「1 分おき」のはずの巡回が、1 回 181〜480 秒かかっていた
楽天市場の巡回は、1 分おきのつもりでした。実測では、1 回に 181〜480 秒かかっていました。害は、三重でした。
- 同時実行の枠を、ほぼ常に 1 つ占有する。
- 480 秒の上限でタイムアウトする(2 時間に 4 回)。結果は捨てられる。
- その間ずっと、楽天の API の枠(1.5 秒に 1 回、全部の処理で共有)を握るので、先着の本命の瞬殺監視の取り分が減る。
実質の間隔は、3.5〜6 分。しかも、タイムアウトで打ち切られると、毎回、同じ先頭のジャンルからやり直すので、後ろのジャンルに順番が回りません。
楽天ブックス側で実績のある、5 ジャンルずつの持ち回りに揃えました。
| 前 | 後 | |
|---|---|---|
| 1 回の所要 | 181〜480 秒 | 50〜83 秒 |
| タイムアウト | 2 時間に 4 回 | 0 回 |
| 1 ジャンルあたりの間隔 | 3.5〜6 分 | 3 分 |
ここで、もう 1 つ見つけました。「前回がまだ走っているなら、始めない」ための鍵(二重実行を防ぐ仕組み)の有効期限が、55 秒しかありませんでした。上限 480 秒、実測 181〜480 秒の処理では、実行係の見送りをすり抜けた回(手動の実行、再起動直後の追い実行)で、二重に走りうる状態でした。楽天 API を 2 倍使うので、先着の監視を直撃します。期限を、どちらも 480,000 ミリ秒に直しました。鍵の期限は、処理のタイムアウト以上にします。
3. 数えても直せない異常を、数え続けない
直す手段がないものを数え続けると、本物の異常が埋もれます。3 つを見直しました。
- 「抽選なのに締切なし 77 件」を 0 件に。実データ 89 件の本文を全部調べると、締切らしい日付があるのは 5 件だけで、その 5 件も「抽選発表 9/5」「受け取りは 9/13 まで」のような、応募の締切ではありませんでした。店が書いていないだけで、直す手段がありません。本文に、締切の言い回しと日付が両方あるものだけを、異常として数えます。
- 「スクレイパー停止 3 件」を 0 件に。数えていたのは、処理ではなく、状態を記録しただけの項目(実行時刻を持たない)でした。本体は除外しているのに、監査だけが揃っていませんでした。
- ある店の「173 時間 0 件」は、正常でした。3 つのカテゴリを取ると、ページは取れていて(16 件と 6 件)、その全部が「ポイント交換専用」(0 円)でした。抽選や予約が、今は無いだけです。
ただし、「取得 0 件」には、2 つの意味があります。(a) 条件に合う商品が無い(正常)。(b) ページの作りが変わって、1 件も読めない(故障)。区別できないと、本物の故障が埋もれます。(前日のポケモンセンターが、まさにこれでした。)そこで、走査した件数を、完了のメッセージに出すようにしました。
4. 測ったうえで、あえて入れなかった案
定価が分からない商品が 397 件ありました。定価が無いと、先着の通知が止まります。補完の処理は、実測すると、成果ゼロでした。
定価が未設定: 397 件
正規の店の価格がある: 51 件
2 店以上が一致: 0 件
「2 店以上が一致」という条件が、実質、一度も成り立たない条件になっていました。1 店でよしとすれば、51 件が埋まります。全部、公式カタログに定価が載っていない種類(マジックの輸入版など)でした。
それでも、入れませんでした。正規の店は、値引きをします。値引き後の価格を定価として記録すると、価格の審査の上限(定価 × 1.08 + 余裕)が、本物の定価より低くなり、正規の出品を、転売として消す方向に間違えます。10% 引きなら、本物の定価は 1.11 倍で、上限を超えます。しかも、消しすぎは、苦情が出ないので、気づけません。
入れるなら、先にやることを書き残しました。
- 51 件の価格を、公式サイトやメーカー希望小売価格と、目で突き合わせる(値引き後かどうかを、実際に確かめる。推測で係数を掛けない)。
- 1 店だけが根拠だと分かる印を付け、その印のときだけ、上限に余裕を足す。
- 入れたあと、非表示になった記事の数を、前後で数える。
分かったこと
偏りは、数えるまで見えない。入れない判断も、記録する。
- 時刻の偏りを、数える。4 時に 27 本、10〜21 時に 0 本。
- 上限が見えない処理は、必ず何かを握る。鍵の期限は、タイムアウト以上に。
- 直せないものを、異常として数えない。数が合わないときは、数え方を疑う。
- 「0 件」の意味を、区別する。走査した件数を出す。
- 「入れない」と決めたら、理由と、入れる条件を残す。測って、成果が出ても、消しすぎる危険があれば、入れません。
この話に出てくるもの
- トレカダッシュ — トレカの抽選・予約・先着の情報を集める iPhone アプリ
- 同時実行の枠を増やす前に見るもの — 枠を握る処理の話
- 「重複は実質ゼロ」と数えたのに、監査は 112 組を出していた — 監査を疑った話
- 自分で作った仕組みが、自分を傷つけた 4 つの記録 — 消えない警告の話
ほかの記録
- 公式の一覧から、「作品名だけの商品」が 393 件できていた:商品名の欄に、商品の形は入っていなかった — 公式サイトの一覧を取り込むと、この日だけで商品が 502 件できた(ふだんは 1〜10 件)。商品名の欄は作品名だけで、形はカテゴリ側にあった。393 件を掃除し、328 件を正しい名前で入れ直すと、別表記のぶつかりが 0 組から 250 組になった。
- 「同じ応募ページ」なら「同じ店」と決めつけていた:店名が別の店になった記事 52 件 — 同じ応募ページの記事の店名を書き揃える処理が、仙台駅前店を「新宿南口店」にしていた。応募ページは 15 の別々の店が共有していた。「確かめられたときだけ揃える」に直し、52 件を、触っていない項目から復元した記録。
- 先着が始まった瞬間、サイトが順番待ちのページになる:8,000 バイトの関門を、15KB の案内ページがすり抜けた — イオンスタイルオンラインで先着が始まると、全体が「アクセス集中」の 15KB のページになった。同じ日の先に入れた 8,000 バイト未満の関門をすり抜け、「成功・商品 0 件」と読まれていた。題名で見る関門に直し、Amazon の 13 分が直列の AI 審査だったことも分かった。
コメント
感想や、記事の間違いの指摘は、ここへ。書くには、GitHub のアカウントが要ります。
押すと、giscus(giscus.app)と GitHub に接続します。押さなければ、接続しません。詳しくはあつかいに書いています。