thread-master/old/docs/architecture.md

277 lines
11 KiB
Markdown
Raw Normal View History

2026-07-09 03:45:28 +00:00
# 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 刷新等 |
技術主幹:
```text
Go (go-zero) API + Mongo + Redis
+ Go workers吃 Redis job queue
+ Node/Playwright workers8D 風格分析、關鍵字搜尋工具)
+ React 正式前端backend/web
+ Chrome extensionThreads session目前前端同步刻意關閉
```
---
## 2. 目錄地圖
```text
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. 怎麼跑起來
```bash
# 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 :5173proxy 到 API
```
| 服務 | 埠 |
|------|-----|
| API gateway | 8890 |
| 前端 Vite | 51735199 |
| keyword-search tool | 9101 |
| resolve-media tool | 9102 |
健康檢查:`curl http://127.0.0.1:8890/api/v1/health`
首次帳號:`make init`建索引、權限、admin。註冊一般會員需 **admin JWT**(封閉註冊)。
---
## 4. 請求怎麼走
```text
Browser / Worker
→ (nginx 可選)
→ go-zero Server (gateway.go)
→ middlewareJWT / MemberAuth / WorkerSecret
→ handlerparse + validate
→ logic讀 actor、組 request
→ model/usecase業務
→ repositoryMongo / 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>` |
| AIprovider 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 nanosecondsUTC**
- 列表:`?page=&pageSize=`,回傳 `data.pagination` + `data.list`(部分舊 API 仍用 `limit`,屬技術債)
---
## 5. Job 系統(最重要的背景機制)
長任務一律走 job不要在 HTTP request 裡跑 Playwright / 長 LLM。
```text
CreateRunAPI 或內部)
→ Mongo 寫 runpending
→ 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 updatelock 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** claimPlaywright 爬公開頁 |
| 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
### 兩條產品流
```text
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. 建議閱讀順序
1. 本文件 + `AGENTS.md` 核心原則
2. `backend/gateway.go``internal/svc/service_context.go`DI 全貌)
3. `internal/handler/routes.go`(有哪些 API
4. 挑一條線跟到底,例如:
- 登入:`logic/auth` → `model/auth`
- 建 job`logic/job` → `model/job/usecase` → Redis
- 海巡掃描:`logic/placement_topic` → worker `scan_placement.go`
5. 前端:`web/src/App.tsx` → 某一頁 → `api/haixun.ts`
6. Job 細節:`backend/docs/job-system-plan.md`
---
## 9. 常見陷阱
1. **路徑名**repo 是 `backend/`,文件可能寫 `haixun-backend/`
2. **假成功**:歷史上部分 goctl stub 會 `return nil` → HTTP 200清理後不應再有。
3. **兩個 token**:會員 JWT ≠ AI provider keyheader 用途不同。
4. **worker 與 gateway**gateway 不一定 claim job少起 worker 時長任務會卡 queued。
5. **inline workers**:本機 gateway 可能偷偷起 3 個 copy workerprod compose 要自己對齊。
6. **時間**nano 不是毫秒Node 端有時是 ms 精度假 ns。
7. **DevHeaderFallback**:本機 yaml 可用 `X-Tenant-ID`/`X-UID` 跳過 JWTprod 必須關。
---
## 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 / 開發規範 |