Skip to content

13 代码地图与事实索引(面试前抽查用) ​

用途:正文里的行号会随代码迭代漂移,不要背行号。面试前用这一篇按符号名抽查几处,确认口径没变。 每节格式:要证明什么 → 文件(符号)→ 一句话事实 → 复查命令。


一、30 秒复查脚本(面试前跑一遍,确认关键事实没变) ​

bash
cd /Users/binhy/Binhy-Projects/shatangAI

# ① 数据库是 PostgreSQL(不是 MySQL)
grep -n '"pg"' backend/package.json && grep -n "postgres:17" compose.yml
grep -rn "mysql2" backend/package.json || echo "✅ 无 mysql2"

# ② 供应商:只有腾讯云在跑
sed -n '1,30p' backend/services/video/providers/index.ts

# ③ 部分唯一索引还在
grep -rn "WHERE status = 'held'" backend/migrations/*.sql

# ④ 轮询超时与间隔表
grep -n "POLL_INTERVALS_SEC\|POLL_TIMEOUT_MS\|MAX_POLL_ATTEMPTS" backend/services/queue/pollTimeoutPolicy.ts

# ⑤ 启动/周期恢复 + 对账巡检的调度
grep -n "recoverStalledTasks\|recoverOrphanedCreditHolds\|creditAudit\|setInterval" backend/index.ts

# ⑥ 自管链路的拦截清单(数一下几条)
grep -c "recovery\] Skip" backend/services/taskRecovery.ts

# ⑦ 测试规模
find backend -path '*__tests__*' -name '*.test.ts' | wc -l
ls backend/migrations/*.up.sql | wc -l

# ⑧ 类型强度(诚实边界)
grep -rn "@ts-nocheck" backend --include=*.ts | wc -l
grep -n '"strict"' tsconfig.json backend/tsconfig.json admin/tsconfig.json

二、按主题索引 ​

A. 任务队列与生命周期(你的主场,必须全熟) ​

要证明什么文件(符号)一句话事实
提交队列定义与 jobId 去重backend/services/queue/videoQueue.ts(getQueue / enqueueVideoTask / forceEnqueueVideoTask)jobId = taskId;attempts: 1(业务自己重试);enqueueVideoTask 当前无调用方,只有恢复逻辑用 forceEnqueueVideoTask
提交 Worker 的幂等与阶段推进backend/services/queue/videoWorker.ts(executeTask)三层守卫(终态跳过 / 历史权威 / 已有外部号不重复提交);submitting → polling 后立刻投轮询 job
自管链路的 skip 清单同文件 :67-94longVideo / shots / script-library 三条;注释里写了完整资损链(空 prompt 烧钱出废片)
轮询队列(冒号 jobId 坑)backend/services/queue/videoPollQueue.ts(safeJobIdPart)BullMQ 的 jobId 不能含 :;delay=0 时故意不带 jobId
轮询 Worker 主流程backend/services/queue/videoPollWorker.ts(processStandardPollJob)四态归一化;自管链路前置拦截(字幕擦除 volcengine、换脸 tencent-mps 不在注册表里)
收尾(最强的一段)同文件 finalizeStandardTask音轨校验 → Redis SET NX 抢占 → 超分 → 转存 → 写库 → 最后才结算
轮询超时策略backend/services/queue/pollTimeoutPolicy.ts间隔表 [10,10,10,15,20,30,30,30];2 小时由表反推(MAX_POLL_ATTEMPTS=243)
崩溃恢复backend/services/taskRecovery.ts(recoverStalledTasks)启动 + 每 10 分钟;9 条自管链路拦截;Case 1/2 分支;启动强制覆盖 active
供应商任务不存在判定backend/services/queue/providerNotFound.ts先剥随机 RequestId 再匹配(判 not_found 会直接退款,宁可漏判)
僵尸 job 清理backend/scripts/clean-zombie-polls.ts手工脚本,不在定时任务里;默认 dry-run
僵尸/存活心跳backend/index.ts启动顺序:迁移 → Redis → 8 个 Worker → 恢复(任务/积分/支付)→ 每 10 分钟巡检

B. 积分与钱 ​

要证明什么文件(符号)一句话事实
冻结表 + 部分唯一索引backend/migrations/009_credit_holds.up.sql这条迁移是你写的(1/1 提交);UNIQUE (task_id) WHERE status='held'
真冻结(事务内)backend/services/user/userCreditsStore.ts(holdCredits)扣减 + hold + 流水在同一事务;冲突则 throw 回滚
立即扣减 + 事后补日志同文件(consumeUserCredits / journalCreditHold)主流 /generate 链路走这条 → 有"已扣款未建任务"窗口
结算 / 退款(CAS 幂等)同文件(settleCredits / settleCreditsWithAdjustment / refundCredits)都是 WHERE status='held';差额结算 refundOnly(只退不补)
双余额拆分backend/services/billing/creditSplit.ts先扣赠送池;退款按冻结时记下的原比例
拆分不变式backend/migrations/20260823100000_dual_credit_ledger_check.up.sqlCHECK (gift_credits + paid_credits = credits)
悬空冻结恢复backend/services/creditRecovery.ts扫 held 超 10 分钟;ve_ 前缀最先分流
对账巡检(五类异常)backend/services/billing/creditAudit.ts漂移 / 拆分漂移 / 多退 / 悬挂 / 负余额;多退按金额不按笔数
兜底扣费的双重幂等backend/services/queue/videoPollWorker.ts(deductCreditsIfNeeded)同时查流水和 credit_holds;注释记着 37 单/14 用户/370 分事故
按实际时长结算口径backend/services/billing/deliveredDurationSettlement.ts只退不补 / ceil / 失败回落原结算
锁backend/services/lock/creditLock.tsSET NX EX 10 + Lua 比对释放;拿不到不阻断

C. 支付与鉴权 ​

要证明什么文件一句话事实
渠道抽象backend/services/payment/channels/types.tscreateOrder / queryOrder / closeOrder / isConfigured;ChannelId = wechat_native | alipay_precreate
微信支付(你写的)backend/services/payment/wxpayClient.ts手写 HTTP;WECHATPAY2-SHA256-RSA2048 签名、RSA 验签、AES-GCM 解密(末 16 字节取 tag)
回调路由(raw 顺序)backend/routes/payment.ts + backend/index.tsexpress.raw 必须在全局 express.json() 之前注册
入账四层幂等backend/services/payment/creditTopupService.ts订单行 FOR UPDATE + credit_idempotency_key 短路 + crediting 中间态 + UNIQUE 兜底
关单判定纯函数backend/services/queue/pollDecision.ts本地过期 ≠ 上游未付;严格大于(宁可多等不误关)
启动恢复backend/services/payment/paymentRecovery.ts先查上游再关单;查单失败保留重试
微信扫码登录(你写的)backend/services/wechat/wechatOAuth.ts开放平台 snsapi_login;state 存 Redis 防重放
JWTbackend/services/auth/userToken.tsHS256 / 7d;SECRET_KEY 有硬编码兜底(已知风险)
身份解析backend/middleware/userResolver.ts验签 + 实时比 token_version → 覆写 x-login-user;LEGACY_HEADER_AUTH 决定裸头是否采信
限流backend/middleware/rateLimiter.tsIP+path 固定窗口 + 按用户名的动作配额(要保护的是账号里的钱)

D. 供应商与合成 ​

要证明什么文件一句话事实
只有腾讯云在跑backend/services/video/providers/index.tsresolveProvider() 恒返回 'tencent-vod';老实现保留是为了在途任务轮询
Provider 契约backend/types/providers.tscreateTask / queryStatus / poll / generateVideo
能力表backend/services/video/modelCapabilities.ts{maxRefImages, maxSegmentSec, supportsEdit};查表前要归一到基础模型 id
模型/定价目录backend/services/modelCatalog.tsretired 通道 → 腾讯替身映射;pricingServiceKey 显式字段
首尾帧降级backend/services/video/providers/tencentVod.ts有参考媒体时 FirstFrame/LastFrame 强制降级为 Reference
多段一致性(四层)backend/services/queue/productionWorker.ts尾帧→首帧锚 + 音色锚;段三态机 generated/done + planFingerprint 复用
提示词约束backend/services/production/promptCompiler.ts承接块 + 尾帧定格(被称为"连贯性链的单点故障");硬约束置底
拼接(自研 ffmpeg)backend/services/production/stitcher.ts逐段归一化 → concat;loudnorm 改"先测量再线性增益"
ffmpeg 封装backend/services/media/mediaUtils.tsexecFile 调系统二进制,FFMPEG_PATH 可覆盖
音轨门禁backend/services/media/videoAudioGuard.ts必须有可用音轨,否则阻止发布 + 退款 + 告警
生成方式清单backend/services/navCatalog.ts19 个导航标签 / 14 种真实生成方式

E. 存储与文件生命周期 ​

要证明什么文件一句话事实
存储适配器backend/services/storage/index.ts实际只有 2 个后端(OSS + 本地);isRealOssEnabled() 为假时静默降级到本地磁盘
引用存在性判定backend/migrations/20260709120000_oss_delete_queue_guard.up.sql(oss_key_in_use)跨 12+ 张业务表判断;后续迁移扩充到对话/脚本快照
生命周期服务backend/services/storage/ossLifecycleService.ts临时 7 天 / 待删 30 天;物理删除前四处复检
四次误删事故20260709120000 / 20260709160000 / 20260709170000 / 20260909120000 迁移注释"先全删再全插";中文文件名 percent-encoding 造成双杀链;try_ons 跨素材共享被误伤;对话快照未覆盖 → 1638 处引用约 1136 处失联

F. 基础设施与工程化 ​

要证明什么文件一句话事实
发布脚本scripts/deploy.sh7 步、set -euo pipefail、HEAD 断言、按 pm_cwd 推断进程名、探活期望 401
基础设施容器compose.yml只有 PG 17 + Redis 7,无 app service;默认值与生产不一致
配置收口backend/config/index.ts181 个 env、约 33 个顶层配置键(25 个分组 + 8 个标量)、IIFE 派生 enabled;零必填校验
自研迁移backend/scripts/migrate.ts + backend/services/db/migrationRunner.tschecksum 校验、重复版本检测硬失败;无 advisory lock
连接池backend/services/db.tsmax 20 / min 2 / idle 30s / maxUses 7500;缺 statement_timeout 与 ssl
CI.github/workflows/ci.yml只有后端单测一个 job;2026-08-08 起因欠费未执行
hook.githooks/pre-push跑后端单测,但 core.hooksPath 未设置 → 未安装
健康检查backend/index.ts(/api/health)查 PG + Redis + ffmpeg/ffprobe,返回 ok/degraded

G. 前端 ​

要证明什么文件一句话事实
路由src/router/routes.tsxreact-router 7,真路由(约 57 条)
请求层(两套并存)src/shared/lib/apiClient.ts + src/shared/utils/request.ts前者 139 处引用(401 登出 / 402 充值 / 429 toast)
App.tsx 已不存在src/(无 App.tsx)已拆成 page + feature hook;巨型转移到 useAssistantChat.ts 等 hook
长任务轮询features/video-history/useVideoHistoryreact-query refetchInterval:非终态 3 秒,终态停止
进度条真相useDisplayProgress / getDisplayProgressmax(真实/持久化/模拟/阶段下限) 后 min 到 cap;模拟用 mulberry32 播种
管理后台admin/独立应用;唯一 strict:true 且 build 跑 tsc -b;Recharts 三张图
共享规则shared/*.json前后端共用 9 份 JSON(错误词典、分镜、计价等)

三、"作者归属"复查(面试前务必确认一次) ​

bash
cd /Users/binhy/Binhy-Projects/shatangAI
for f in backend/services/taskRecovery.ts backend/services/queue/videoWorker.ts \
         backend/services/user/userCreditsStore.ts \
         backend/migrations/009_credit_holds.up.sql \
         backend/services/payment/wxpayClient.ts \
         backend/services/wechat/wechatOAuth.ts \
         backend/services/queue/productionWorker.ts \
         backend/services/modelCatalog.ts; do
  tot=$(git log --oneline -- "$f" | wc -l | tr -d ' ')
  me=$(git log --oneline --author=se_hyxiong@163.com -- "$f" | wc -l | tr -d ' ')
  printf "%-56s total=%-4s mine=%s\n" "$f" "$tot" "$me"
done

当前结论(可作为"我负责哪块"的依据)

模块你的占比说法
taskRecovery.ts14/33我主导
videoWorker.ts10/19我主导
videoPollQueue.ts你起的头我引入的
userCreditsStore.ts11/45核心实现我参与
creditRecovery.ts3/9我参与
009_credit_holds.up.sql1/1完全是我写的
wxpayClient.ts2/2我写的
wechatOAuth.ts1/1我写的
userResolver.ts1/3我参与(JWT 覆写身份那层)
rateLimiter.ts1/7我参与(用户名维度配额)
productionWorker.ts0/35同事主导 → 只说"我从恢复和结算侧参与,能讲清分段续跑"
modelCatalog.ts0/30同事主导 → "模型与定价的权威清单,我读过但不负责维护"

四、口径漂移的四个高危点(每次面试前重新确认) ​

高危点为什么容易漂确认方式
供应商数量与"唯一通道"上游一直在变(半年内从火山切到腾讯)看 providers/index.ts 的 resolveProvider 返回什么
enqueueVideoTask 有没有调用方一旦有人开始用队列提交,bullet ① 的说法要改grep -rn "enqueueVideoTask" backend --include=*.ts
LEGACY_HEADER_AUTH 生产取值决定 X-Login-User 能否被伪造,仓库里查不到上服务器查 backend/.env
SECRET_KEY 生产取值若是默认值 = 完整认证绕过上服务器查 backend/.env(最优先)

五、仓库里"会误导你"的文档(别拿它们当依据) ​

文档问题
ARCH.md停留在 TS 迁移早期:写"App.tsx 约 10k 行""无自动化测试""51 个文件迁移完成",全部过期
README.md写"MySQL 存储用户和积分数据"(错的)、USE_DB_AUTH(代码 0 命中)、"跳过 provider='unknown'"(该分支不存在)
CHORE.md不是技术债日志,是"TS 迁移 Agent Prompt";写"51 个文件全量迁移、tsc 零错误"与现状严重不符
docs/architecture/provider-integration-guide.md写"默认 kuaizi""MYNEW_PREFER 灰度开关""按 model 前缀路由"——代码里全都不存在
docs/db.md标题写"生产级高可用 PostgreSQL",实际内容是规划阶段待评审,引用的 dbHealth.ts 从未创建
ARCH.md / docs/* 里的"零错误"表述实际:根与 backend strict: false、后端 54 个 @ts-nocheck

结论:本套材料以代码为准;给面试官引文档时,只引"迁移注释里的历史事故记录",那是真实证据。

持续学习,持续构建。