11 KiB
Thread-Master / 巡樓後端 — 架構導覽
這份文件幫助你快速理解整個 monorepo 在幹什麼,以及程式碼該從哪裡讀。
更細的 agent 規則見根目錄 AGENTS.md;產品方向(文案流重做)見 docs/post-project-plan.md。
1. 這是什麼專案?
巡樓 Console + 後端:給 Threads 經營者用的工作台。
| 能力 | 白話 |
|---|---|
| 帳號 / OAuth | 綁 Threads 帳號、token 刷新、連線診斷 |
| 人設 (Persona) | 風格分析(8D)、語調、知識素材 |
| 文案 / 任務 (Missions) | 主題發想、矩陣產稿、草稿排程(過渡期實作) |
| 海巡 (Patrol) | 依品牌/主題找貼文、知識圖譜、外展草稿 |
| 發布 (Publish) | 排程 queue、護欄、成效、提及回覆 |
| Job 系統 | 所有長任務:爬蟲、AI 產稿、token 刷新等 |
技術主幹:
Go (go-zero) API + Mongo + Redis
+ Go workers(吃 Redis job queue)
+ Node/Playwright workers(8D 風格分析、關鍵字搜尋工具)
+ React 正式前端(backend/web)
+ Chrome extension(Threads session,目前前端同步刻意關閉)
2. 目錄地圖
thread-master/
├── AGENTS.md # 寫碼/分層/時間/錯誤碼規範
├── Makefile # 全 repo 指令入口
├── docs/ # 產品與架構文件(本檔)
├── scripts/dev-all.sh # 一鍵起本機完整 stack
├── infra/ # Mongo/Redis、nginx、systemd
├── deploy/ # 正式 compose、env 範本
├── extension/ # Chrome 擴充
└── backend/ # ★ 主產品(模組名 haixun-backend)
├── gateway.go # API 程序入口
├── cmd/worker/ # Go worker 程序入口
├── cmd/tool/ # init(索引、admin)
├── generate/api/*.api # API 契約(goctl)
├── etc/*.yaml # 設定
├── internal/
│ ├── handler/ # HTTP 進出口
│ ├── logic/ # API 編排(不碰 Mongo 直接存取)
│ ├── model/ # domain + usecase + repository
│ ├── worker/job/ # step handler、scheduler、reaper
│ ├── library/ # 共用能力(threads、placement、viral…)
│ ├── middleware/ # JWT、RBAC、worker secret
│ ├── svc/ # DI 組裝 ServiceContext
│ └── response/ # JSON envelope
├── web/ # 正式 React Console
├── worker/ # Node/Playwright
└── docs/ # job-system、gap 等後端計劃
文件裡有時寫
haixun-backend/,在 monorepo 裡就是backend/。
3. 怎麼跑起來
# 1. 環境
cp deploy/.env.dev.example deploy/.env.dev # 填 Mongo/Redis/JWT/Worker secret
# 2. 資料庫
make dev-infra
# 3. 一鍵:API + Go workers + Node tools/worker + 前端
make dev-all
# 或拆開
make run # API :8890
make web-dev # Vite :5173,proxy 到 API
| 服務 | 埠 |
|---|---|
| API gateway | 8890 |
| 前端 Vite | 5173–5199 |
| keyword-search tool | 9101 |
| resolve-media tool | 9102 |
健康檢查:curl http://127.0.0.1:8890/api/v1/health
首次帳號:make init(建索引、權限、admin)。註冊一般會員需 admin JWT(封閉註冊)。
4. 請求怎麼走
Browser / Worker
→ (nginx 可選)
→ go-zero Server (gateway.go)
→ middleware(JWT / MemberAuth / WorkerSecret)
→ handler(parse + validate)
→ logic(讀 actor、組 request)
→ model/usecase(業務)
→ repository(Mongo / Redis)或 library adapter
→ response.Write { code, message, data, error }
分層規則(必守)
| 層 | 可以做 | 不可以做 |
|---|---|---|
| handler | parse、validate、呼叫 logic | 業務判斷、直接 Mongo |
| logic | 編排 usecase、組 payload | import model/*/repository |
| model/usecase | 可重用業務 | 知道 HTTP |
| AI provider adapter | 呼叫外部 AI | 讀 setting、Mongo、HTTP context |
| worker step | 透過 job usecase 更新進度 | 裸 Update 蓋 job 狀態 |
Auth 重點
| 路由類型 | Header |
|---|---|
| 一般保護 API | Authorization: Bearer <會員 JWT> |
| AI(provider key 占 Authorization) | X-Member-Authorization + Authorization: <provider key> |
| 內部 worker | X-Worker-Secret |
Access token 由 /api/v1/auth/login|refresh 簽發。AI key 每次 request 帶入,不寫進 config。
時間與列表
- 儲存/API 時間欄位:unix nanoseconds(UTC)
- 列表:
?page=&pageSize=,回傳data.pagination+data.list(部分舊 API 仍用limit,屬技術債)
5. Job 系統(最重要的背景機制)
長任務一律走 job,不要在 HTTP request 裡跑 Playwright / 長 LLM。
CreateRun(API 或內部)
→ Mongo 寫 run(pending)
→ Redis 佇列 jobs:queue:<workerType>
Worker ClaimNext
→ BRPOP → TryLock(jobID, workerID)
→ status → running
→ 依 template steps 執行 handler
→ Heartbeat 續 lock
→ CompleteRun / FailRun / AcknowledgeCancel
| 元件 | 檔案 |
|---|---|
| 建立 / claim / 完成 | internal/model/job/usecase/usecase.go |
| Redis queue/lock | internal/model/job/repository/redis_queue.go |
| Go runner | internal/worker/job/runner.go |
| 排程 / reaper | scheduler.go / reaper.go |
| 設計文件 | backend/docs/job-system-plan.md |
規則: 狀態轉移用 guarded update;lock value = workerID;release 必須檢查 owner。
程序角色
| 程序 | 職責 |
|---|---|
| Gateway | HTTP;可跑 scheduler/reaper/token/publish sweeper;通常不 claim job |
| Go worker(一 type 一 process) | 消費對應 queue、跑 step handler |
| Node style-8d | 經 HTTP internal API claim,Playwright 爬公開頁 |
| Node keyword/media | 被 Go 呼叫的 HTTP 工具,不是 job consumer |
Gateway 在 JobWorker.Enabled=false 時,仍可能 inline 起 topic/formula/rewrite 三個 copy worker(見 internal/svc/job_workers.go)。
6. 產品功能地圖(前端 ↔ 後端)
前端是 hash 路由(App.tsx),沒有 React Router。
| Hash | 頁面 | 主要後端域 |
|---|---|---|
#dashboard |
總覽 | accounts、jobs、publish summary |
#accounts |
Threads 帳號 | threads_account、OAuth、guard |
#brands |
品牌 / 產品 | brand |
#personas |
人設 / 8D | persona、style_preset、style-8d job |
#missions |
文案工作台 | inspire、content_ops、copy_draft、matrix/formula/rewrite jobs |
#patrol |
海巡獲客 | placement_topic、knowledge_graph、scan_post、outreach |
#publish |
發布 / 回覆 / 自家貼 | publish_queue、mention_inbox、own_post_formula |
#jobs |
任務監控 | job runs / schedules / events |
#settings |
會員 / AI | member、placement settings |
#gaps |
靜態路線圖 | 無 API |
#register |
管理員建會員 | auth register(需 admin) |
API client:backend/web/src/api/haixun.ts + client.ts(envelope、refresh、502 retry)。
兩條產品流
Flow A 文案營運(過渡)
MissionsPage → inspire / content plans / matrix / drafts → publish_queue
舊 copy_mission 完整 pipeline 已半拆(見 post-project-plan)
Flow B 海巡獲客
Brands + PatrolPage → 主題 → 圖譜 → 掃描貼文 → outreach 草稿 → 發布
docs/post-project-plan.md 計劃用 Post Project 取代 Flow A 舊 pipeline。
7. 後端 model 一覽(讀碼用)
| model | 用途 | 前端是否主用 |
|---|---|---|
| auth / member / permission | 登入與 RBAC | 是 |
| setting | 通用 KV | 弱(多半用 typed settings) |
| ai | provider 抽象 + SSE | 設定頁 / AI 路由 |
| job | 模板 / run / schedule / event | Jobs + 各頁輪詢 |
| threads_account | 帳號、OAuth、token | 是 |
| persona / style_preset | 人設 | 是 |
| content_ops | 主題候補、content plan、知識、feedback | Missions |
| content_formula / own_post_formula | 公式 / 自家貼分析 | Publish / Missions |
| copy_draft | 文案草稿 | Missions |
| copy_mission | 舊文案任務實體 | 幾乎不用(僅邊角耦合) |
| brand / placement_topic | 品牌與海巡主題 | Brands / Patrol |
| knowledge_graph | 知識圖譜 | Patrol |
| scan_post / outreach_draft | 掃描貼文與外展 | Patrol |
| publish_* | queue / guard / inventory / analytics / events | Publish / Dashboard |
| mention_inbox | 提及收件 | Publish |
| (已移除)crm_contact / publish_draft scaffold | 見 docs/cleanup-log.md |
— |
業務重邏輯常在 internal/library/(placement、viral、threadsapi、prompt…),不是 model/。
8. 建議閱讀順序
- 本文件 +
AGENTS.md核心原則 backend/gateway.go→internal/svc/service_context.go(DI 全貌)internal/handler/routes.go(有哪些 API)- 挑一條線跟到底,例如:
- 登入:
logic/auth→model/auth - 建 job:
logic/job→model/job/usecase→ Redis - 海巡掃描:
logic/placement_topic→ workerscan_placement.go
- 登入:
- 前端:
web/src/App.tsx→ 某一頁 →api/haixun.ts - Job 細節:
backend/docs/job-system-plan.md
9. 常見陷阱
- 路徑名:repo 是
backend/,文件可能寫haixun-backend/。 - 假成功:歷史上部分 goctl stub 會
return nil→ HTTP 200;清理後不應再有。 - 兩個 token:會員 JWT ≠ AI provider key,header 用途不同。
- worker 與 gateway:gateway 不一定 claim job;少起 worker 時長任務會卡 queued。
- inline workers:本機 gateway 可能偷偷起 3 個 copy worker,prod compose 要自己對齊。
- 時間:nano 不是毫秒;Node 端有時是 ms 精度假 ns。
- DevHeaderFallback:本機 yaml 可用
X-Tenant-ID/X-UID跳過 JWT,prod 必須關。
10. 相關文件
| 文件 | 內容 |
|---|---|
docs/architecture.md |
本導覽 |
docs/improvement-notes.md |
前後端可改進處 |
docs/cleanup-log.md |
已清除的死碼紀錄 |
docs/post-project-plan.md |
文案流(Flow A)重做計劃 |
backend/docs/job-system-plan.md |
Job 系統設計 |
backend/docs/threads-automation-gap-plan.md |
自動營運 gap(部分已落地) |
backend/README.md |
後端 README / API 慣例 |
AGENTS.md |
Agent / 開發規範 |