thread-master/docs/product/demand-radar/tasks/T501-mongo-indexes-radar-cr...

4.4 KiB
Raw Permalink Blame History

T501 — mongo-indexes-radar-crm

Status: done2026-07-31
Milestone: M0
Kind: feat
Est. change: ~120 lines

Goal

完成後系統應:make init 可重複執行並建立本 run 全部 collection 索引,含去重唯一鍵。

Depends on

Inputs

  • Spec../spec.md §8實體與索引
  • 既有索引初始化:apps/backend/cmd/init/main.go

Outputs

程式變更(預期路徑)

路徑 動作 說明
apps/backend/generate/database/mongo/000014_demand_radar_indexes.up.json add 全部 15 個索引,含兩個 unique
apps/backend/generate/database/mongo/000014_demand_radar_indexes.down.json add 對應 dropIndexes
apps/backend/cmd/init/main.go edit 七個 collection 的非 unique 索引(名稱與 spec 與 migration 完全一致)

行為變更

  • 建立索引:
    • radar_service_profiles_id = owner_uid(不需額外索引)
    • radar_watches(owner_uid, status)(owner_uid, created_at)
    • radar_sweeps(owner_uid, created_at)(watch_id, created_at)job_id
    • radar_opportunities(owner_uid, created_at)(owner_uid, intent_band, status)(owner_uid, external_id) unique
    • radar_replies(owner_uid, opportunity_id, variant)
    • crm_contacts(owner_uid, source_platform, author_handle) unique(owner_uid, stage, last_touch_at)(owner_uid, needs_follow_up)
    • crm_touches(owner_uid, contact_id, created_at)
    • crm_followups(status, due_at)(owner_uid, contact_id)
  • 重複執行不報錯(沿用既有 idempotent 建法)。

Out of scope

  • domain struct 與 repository各 M 的 model task
  • 資料遷移(本 run 無既有資料需搬)

Acceptance

  • make init 連跑兩次皆成功(乾淨 DB 驗證,兩次都 database indexes initialized
  • Mongo getIndexes() 可見上列索引migrate 路徑 15 個且 unique 恰為 radar_opportunities.owner_opportunity_externalcrm_contacts.owner_contact_identityinit 路徑 13 個非 unique
  • 唯一鍵語意實測:同 owner 同 external_id 第二筆被擋11000、不同 owner 可共存;同 owner 同平台同 handle 第二筆被擋、跨平台可共存
  • migrate-down 1 → 再 up 可逆
  • 指令radar/crm 部分;完整鏈路受既有缺陷阻塞,見下):
cd apps/backend && make migrate-up MONGO_URL=<scratch> && MONGO_DATABASE=<scratch> make init

Notes

(owner_uid, external_id) 是 SW-06 去重的硬保證,不能只靠應用層判斷。

落點分工(沿用 growth-loop 先例)

唯一鍵放 migration、operational 索引放 cmd/initradar/crm 兩邊的索引名稱與 spec 完全一致,因此同一顆 DB 先 migrate 再 init 不會衝突(已實測)。

Mongo 的衝突規則(實測 Mongo 7

情境 結果
同名同鍵、unique 不同 IndexKeySpecsConflict86
同名同鍵同 spec 重建 OKidempotent
異名同鍵同 spec IndexOptionsConflict85"already exists with a different name"
異名同鍵但 spec 不同 允許(會多一個索引)

既有缺陷(非本 task 造成,未修

make migrate-up && make init新 DB 上無法連跑:多個既有 collection 的 migration 與 init 用同鍵不同名init 會在第一個衝突處 panic。已確認的衝突點

Collection migration 名 init 名
notifications (owner_uid, created_at) owner_notifications_recent owner_notifications_created
growth_outcomes (owner_uid, source_type, source_id) owner_outcome_sourceunique 同名但非 unique
growth_checkups (owner_uid, created_at) owner_checkups_recent owner_checkups_created
growth_workspaces (owner_uid, archived) owner_workspaces owner_workspaces_archived
growth_invite_rewards (inviter_uid, created_at) inviter_rewards inviter_rewards_created
growth_invite_rewards (invitee_uid) invitee_reward_once invitee_reward

未修的原因:要決定「以哪邊的名字為準」會影響既有部署——若某環境的索引是 init 建的,把 init 改成 migration 的名字會讓該環境從此報 85。這是需要產品維運決定的收斂方向不該塞在本 task 裡。建議另開 task 處理(含各環境現況盤點)。