Skip to content

feat: Clubs との突合を global_club_id (UUID) に切り替える - #42

Open
yasulab wants to merge 1 commit into
mainfrom
use-global-club-id-for-matching
Open

feat: Clubs との突合を global_club_id (UUID) に切り替える#42
yasulab wants to merge 1 commit into
mainfrom
use-global-club-id-for-matching

Conversation

@yasulab

@yasulab yasulab commented Aug 6, 2026

Copy link
Copy Markdown
Member

coderdojo.jp の /dojos.jsonglobal_club_id を返すようになった(coderdojo.jp#1875)ので、Clubs DB との突合を名前照合から UUID 直結に切り替えます。

名前照合の何が問題だったか

問題 実例
新しい Dojo のたびに dojo2dojo.csv へ 1 行足す運用が必要 追加漏れが実際に起きていた
Clubs 側で改名されると追従できない 那覇の登録名が「CoderDojo Japan Association (Official Regional Body)」に変わっていた
同名クラブが二重登録されていると先に現れた方を拾う 流山・古河

実データで計測した差分

方式 地図に載る日本のクラブ
現行(名前照合) 194
UUID + CSV 救済 202(UUID 200 / CSV 2)

増える 10 件: 播磨科学公園都市 / 八戸@吹上 / 川西 / 明石 / 吉祥寺 / 那覇 / 氷見@bigberries / 豊橋 / 流山 / 古河

流山・古河は消失ではなく、指すクラブ レコードが変わります。 Clubs 側に同名クラブが二重登録されており、現行は先に現れた方を拾っていました。座標差は 0.10 km / 0.15 km です。

Nagareyama    46a7f225-...  jp/nagareyama-chiba-prefecture/nagareyama   ← 現行が拾う
Nagareyama    7d3b2a2d-...  jp/nagareyamacity-chibaprefec/nagareyama    ← Japan 側の UUID が指す

これで active な Dojo 202 件が全件地図に載ります(突合できなかったもの 0 件)。

CSV は救済としてだけ残す

連名道場 2 件(西宮・梅田、大田・邑南、他)は 1 エントリが複数のクラブを表すため、単一の UUID では表せません。この 2 件のために CSV 経路を残します。

救済するかは「UUID を持つか」ではなく「UUID 経路で実際に載ったか」で判定します。 前者だと、Clubs 側でクラブが消えたり UUID が変わったりした時に、CSV に行があっても救済されず地図から静かに消えます。上記のとおり二重登録は実在し、どちらが整理されるかはこちらでは決められません。

静かに壊れる経路を塞ぐ

名前照合には「壊れても縮退して生き延びる」性質がありました。_data/dojos_japan.json が空でも、CSV とローカルのデータだけで日本のマーカーは出ていました(ロゴがデフォルトになるだけ)。UUID 直結にはその性質が無く、入力が空なら日本のマーカーは全滅します。

海外分 1,100 件あまりは残るため、既存の GeoJSON 検査では検出できません。実際に確かめました。

$ echo '[]' > _data/dojos_japan.json && ruby _tasks/upsert_dojos_geojson.rb
DojoMap: 日本のマーカー 0 件 (UUID 突合 0 / CSV 救済 0)

$ ruby tests/markers_integrity_test.rb
9 runs, 22 assertions, 0 failures   # ← 素通りする

日次の Actions が生成物を作ってそのままデプロイする構成なので、次の 3 つを足しました。

追加 内容
ワークフローの件数ガード 日本側データが 300 件未満なら停止(Earth 側の 1000 件ガードと同じ形)
tests/dojo_matching_test.rb 入力と出力の両側に下限。UUID の書式・一意性、マーカーの重複を検査
突合レポート 載らなかった active な Dojo を理由付きで書き出し、要対応のものだけ Slack 通知

通知は uuid_not_in_clubs(Japan 側が UUID を持つのに Clubs 側にクラブが無い)に限ります。UUID も CSV も無い状態は新しい Dojo を追加した直後にも起きるため、通知すると狼少年になります。デプロイの後に置き、continue-on-error でジョブは落としません。1 つの Dojo が消えただけで日次更新全体を止めるのは割に合わないためです。

検証

  • SKIP_BUILD=true bundle exec rake test → minitest 17 runs 0 failures、HTML-Proofer 成功
  • 入力を空にする / global_club_id を落とす → 新しいテストが落ちることを確認
  • 南城のクラブを Clubs 側から消す → 検知ステップが exit 1 になり Slack 通知に至ることを確認
  • 正常時は exit 0 で通知しないことを確認

検知スクリプトは当初 next を使っていて SyntaxError になり、毎日誤通知が飛ぶ状態でした。上記の正常時テストで見つけて exit 0 if に直しています。

これまで dojo2dojo.csv でクラブ名を突合していたが、次の問題があった。

- 新しい Dojo を追加するたび CSV に 1 行足す運用が必要で、実際に漏れていた
- Clubs 側で改名されると追従できない。那覇は登録名が
  「CoderDojo Japan Association (Official Regional Body)」に変わっていて
  一致しなくなっていた
- 同名クラブが二重登録されていると、先に現れた方を拾ってしまう(流山・古河)

coderdojo.jp の /dojos.json が global_club_id を返すようになったので、
UUID で直接突き合わせる。日本のマーカーは 194 件から 202 件になり、
active な Dojo 202 件が全件地図に載る。

CSV は「まだ UUID を持てない Dojo」の救済として残す。現在は連名道場 2 件
(西宮・梅田、大田・邑南、他)が該当する。1 エントリが複数のクラブを表す
ため、単一の UUID では表せない。

救済するかどうかは「UUID を持つか」ではなく「UUID 経路で実際に載ったか」で
判定する。前者だと、Clubs 側でクラブが消えたり UUID が変わったりした時に、
CSV に行があっても救済されず地図から静かに消える。Clubs 側の二重登録は
実在し、どちらが整理されるかはこちらでは決められない。

## 静かに壊れる経路を塞ぐ

名前突合には「壊れても縮退して生き延びる」性質があった。dojos_japan.json が
空でも、CSV とローカルのデータだけで日本のマーカーは出ていた。UUID 直結には
その性質が無く、入力が空なら日本のマーカーは全滅する。海外分 1,100 件あまりが
残るため、既存の GeoJSON 検査では検出できない(実際に通ることを確認した)。

日次の Actions が生成してそのままデプロイする構成なので、次の 3 つを足した。

- ワークフローに日本側データの件数ガード(Earth 側と同じ形)
- tests/dojo_matching_test.rb: 入力と出力の両側に下限を置き、UUID の書式と
  一意性、マーカーの重複を検査する
- 突合できなかった active な Dojo を tmp/unmatched_dojos.json に理由付きで
  書き出し、要対応のものだけ Slack に通知する

通知は uuid_not_in_clubs に限る。UUID も CSV も無い状態は新しい Dojo を
追加した直後にも起きるため、通知すると狼少年になる。

関連: coderdojo-japan/coderdojo.jp#1616
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant