thread-master/old/docs/architecture.md

277 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 / 開發規範 |