chore: 新增上线检查单与脱敏 env 模板
This commit is contained in:
128
api/.env.example
Normal file
128
api/.env.example
Normal file
@@ -0,0 +1,128 @@
|
||||
# =============================================================================
|
||||
# Life Echo API environment example
|
||||
# 复制为 .env 或 .env.production 后按实际环境修改
|
||||
# 不要把真实密钥提交到仓库
|
||||
# =============================================================================
|
||||
|
||||
# =============================================================================
|
||||
# LLM / DeepSeek
|
||||
# =============================================================================
|
||||
DEEPSEEK_API_KEY=your_deepseek_api_key
|
||||
DEEPSEEK_BASE_URL=https://api.deepseek.com
|
||||
DEEPSEEK_MODEL=deepseek-chat
|
||||
|
||||
# =============================================================================
|
||||
# Database
|
||||
# =============================================================================
|
||||
# 本地开发示例:
|
||||
# DATABASE_URL=postgresql://postgres:postgres@localhost:5432/life_echo
|
||||
# Docker / production 示例:
|
||||
# DATABASE_URL=postgresql://postgres:postgres@postgres:5432/life_echo
|
||||
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/life_echo
|
||||
|
||||
# =============================================================================
|
||||
# Redis
|
||||
# =============================================================================
|
||||
# 本地开发示例:
|
||||
# REDIS_URL=redis://localhost:6379/0
|
||||
# Docker / production 示例:
|
||||
# REDIS_URL=redis://redis:6379/0
|
||||
REDIS_URL=redis://localhost:6379/0
|
||||
REDIS_SESSION_TTL=86400
|
||||
|
||||
# =============================================================================
|
||||
# Auth
|
||||
# =============================================================================
|
||||
# 建议使用: openssl rand -hex 32
|
||||
SECRET_KEY=replace_with_a_strong_random_secret
|
||||
ALGORITHM=HS256
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES=120
|
||||
|
||||
# =============================================================================
|
||||
# Tencent SMS
|
||||
# =============================================================================
|
||||
TENCENT_SMS_SECRET_ID=your_tencent_sms_secret_id
|
||||
TENCENT_SMS_SECRET_KEY=your_tencent_sms_secret_key
|
||||
TENCENT_SMS_SDK_APP_ID=your_sms_sdk_app_id
|
||||
TENCENT_SMS_SIGN_NAME=your_sms_sign_name
|
||||
TENCENT_SMS_TEMPLATE_ID=your_sms_template_id
|
||||
TENCENT_SMS_TEMPLATE_PARAM_COUNT=1
|
||||
|
||||
# =============================================================================
|
||||
# ASR Provider
|
||||
# whisper | tencent
|
||||
# =============================================================================
|
||||
ASR_PROVIDER=whisper
|
||||
|
||||
# Whisper ASR
|
||||
ASR_MODEL_SIZE=small
|
||||
ASR_DEVICE=cpu
|
||||
ASR_COMPUTE_TYPE=int8
|
||||
|
||||
# Tencent ASR
|
||||
# 仅在 ASR_PROVIDER=tencent 时需要
|
||||
TENCENT_SECRET_ID=your_tencent_asr_secret_id
|
||||
TENCENT_SECRET_KEY=your_tencent_asr_secret_key
|
||||
# TENCENT_ASR_APP_ID=
|
||||
|
||||
# =============================================================================
|
||||
# WeChat Pay
|
||||
# =============================================================================
|
||||
WECHAT_PAY_APP_ID=your_wechat_pay_app_id
|
||||
WECHAT_PAY_MCH_ID=your_wechat_mch_id
|
||||
WECHAT_PAY_API_V3_KEY=your_wechat_api_v3_key
|
||||
WECHAT_PAY_PRIVATE_KEY_PATH=certs/apiclient_key.pem
|
||||
WECHAT_PAY_CERT_SERIAL_NO=your_wechat_cert_serial_no
|
||||
WECHAT_PAY_NOTIFY_URL=https://your-domain.com/api/payment/notify/wechat
|
||||
# 可选平台公钥模式
|
||||
# WECHAT_PAY_PLATFORM_PUBLIC_KEY_PATH=certs/wechat_platform_public_key.pem
|
||||
# WECHAT_PAY_PLATFORM_PUBLIC_KEY_ID=your_wechat_platform_public_key_id
|
||||
|
||||
# =============================================================================
|
||||
# Alipay
|
||||
# =============================================================================
|
||||
ALIPAY_APP_ID=your_alipay_app_id
|
||||
ALIPAY_PRIVATE_KEY=your_alipay_private_key
|
||||
ALIPAY_PUBLIC_KEY=your_alipay_public_key
|
||||
ALIPAY_NOTIFY_URL=https://your-domain.com/api/payment/notify/alipay
|
||||
|
||||
# =============================================================================
|
||||
# Misc
|
||||
# =============================================================================
|
||||
ENABLE_TEST_SUBSCRIPTION=0
|
||||
|
||||
# =============================================================================
|
||||
# Memoir image generation
|
||||
# =============================================================================
|
||||
MEMOIR_IMAGE_ENABLED=false
|
||||
MEMOIR_IMAGE_MAX_PER_CHAPTER=2
|
||||
MEMOIR_IMAGE_POLL_INTERVAL=3
|
||||
MEMOIR_IMAGE_MAX_ATTEMPTS=20
|
||||
# 正文越长,可允许更多图片
|
||||
MEMOIR_IMAGE_CHARS_PER_EXTRA=1500
|
||||
MEMOIR_IMAGE_MAX_CAP=8
|
||||
MEMOIR_IMAGE_PROVIDER=liblib
|
||||
MEMOIR_IMAGE_STYLE_DEFAULT=watercolor
|
||||
MEMOIR_IMAGE_SIZE_DEFAULT=1280x720
|
||||
# 可选,限制 Liblib 下载域名
|
||||
# MEMOIR_IMAGE_DOWNLOAD_HOSTS=liblib.cloud,liblibai.cloud
|
||||
|
||||
# =============================================================================
|
||||
# Liblib image provider
|
||||
# =============================================================================
|
||||
LIBLIB_ACCESS_KEY=your_liblib_access_key
|
||||
LIBLIB_SECRET_KEY=your_liblib_secret_key
|
||||
LIBLIB_BASE_URL=https://openapi.liblibai.cloud
|
||||
LIBLIB_TEMPLATE_UUID=your_liblib_template_uuid
|
||||
|
||||
# =============================================================================
|
||||
# Tencent COS for memoir images
|
||||
# 生产环境请确认这里使用的是生产 bucket,而不是开发 bucket
|
||||
# =============================================================================
|
||||
TENCENT_COS_SECRET_ID=your_tencent_cos_secret_id
|
||||
TENCENT_COS_SECRET_KEY=your_tencent_cos_secret_key
|
||||
TENCENT_COS_REGION=ap-shanghai
|
||||
TENCENT_COS_BUCKET=your_production_bucket
|
||||
TENCENT_COS_BASE_URL=https://your_production_bucket.cos.ap-shanghai.myqcloud.com
|
||||
# 可选临时凭证
|
||||
# TENCENT_COS_TOKEN=
|
||||
@@ -96,4 +96,34 @@ ALIPAY_PRIVATE_KEY=...
|
||||
ALIPAY_PUBLIC_KEY=...
|
||||
ALIPAY_NOTIFY_URL=https://lifecho.worldsplats.com/api/payment/notify/alipay
|
||||
|
||||
ENABLE_TEST_SUBSCRIPTION=1
|
||||
ENABLE_TEST_SUBSCRIPTION=1
|
||||
|
||||
# =============================================================================
|
||||
# 回忆录图片生成配置
|
||||
# =============================================================================
|
||||
# 总开关(true 启用,不设置则关闭)
|
||||
MEMOIR_IMAGE_ENABLED=false
|
||||
# 每章最多生成图片数
|
||||
MEMOIR_IMAGE_MAX_PER_CHAPTER=2
|
||||
# 轮询间隔(秒)和最大尝试次数
|
||||
MEMOIR_IMAGE_POLL_INTERVAL=3
|
||||
MEMOIR_IMAGE_MAX_ATTEMPTS=20
|
||||
|
||||
# =============================================================================
|
||||
# Liblib 图片生成 API(HMAC-SHA1 签名认证)
|
||||
# =============================================================================
|
||||
LIBLIB_ACCESS_KEY=zrDp6quCOKlLwcewOEfrog
|
||||
LIBLIB_SECRET_KEY=iTVHo5Nf3KA-xpC1Mja80bC93u6chJem
|
||||
LIBLIB_BASE_URL=https://openapi.liblibai.cloud
|
||||
# 星流 Star-3 Alpha 文生图模板(默认值,可按需切换为其他模型)
|
||||
LIBLIB_TEMPLATE_UUID=5d7e67009b344550bc1aa6ccbfa1d7f4
|
||||
|
||||
# =============================================================================
|
||||
# 腾讯云 COS(回忆录图片存储)
|
||||
# =============================================================================
|
||||
TENCENT_COS_SECRET_ID=AKIDa2ILCwUr56uVt31oU0JOHxPfGhvvkLiq
|
||||
TENCENT_COS_SECRET_KEY=xiFbjlZ9XheS2NWYLvHRPAh2A5nGYcR2
|
||||
TENCENT_COS_REGION=ap-shanghai
|
||||
# 要把bucket改成生产环境的bucket
|
||||
TENCENT_COS_BUCKET=life-echo-dev-1319381411
|
||||
TENCENT_COS_BASE_URL=https://life-echo-dev-1319381411.cos.ap-shanghai.myqcloud.com
|
||||
137
docs/before-prod/production-readiness-summary-2026-03-11.md
Normal file
137
docs/before-prod/production-readiness-summary-2026-03-11.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# Production 上线判断总结(2026-03-11)
|
||||
|
||||
## 结论
|
||||
|
||||
当前代码已经接近可上线状态,但是否可以直接进入 `production`,取决于图片功能的上线策略。
|
||||
|
||||
- 如果接受丢弃历史旧图,并且上线时将 `MEMOIR_IMAGE_ENABLED=false`,则本次改动不需要额外做数据库迁移,整体风险可控,可以作为保守方案进入生产。
|
||||
- 如果准备在生产立即启用章节配图功能,则仍需确认生产 COS 资源、Liblib 凭证、Celery worker 部署和新依赖安装均已就绪,之后再启用更稳妥。
|
||||
|
||||
## 本次评估范围
|
||||
|
||||
本次评估针对 `8b4a058..HEAD` 期间的改动,重点检查了以下内容:
|
||||
|
||||
- 数据库模型和迁移脚本是否变化
|
||||
- API / WebSocket / Celery 是否有生产兼容性风险
|
||||
- 回忆录图片链路是否会影响现网章节读取、阅读页和 PDF 导出
|
||||
- 生产环境变量和容器部署形态是否能承接新能力
|
||||
|
||||
## 数据库与迁移判断
|
||||
|
||||
### 不需要新增 schema 迁移
|
||||
|
||||
本次区间内没有新增数据库表、字段或字段类型修改。
|
||||
|
||||
- `api/database/models.py` 中 `Chapter.images` 只有注释语义变化,从“图片 URL 列表”变成“图片元数据对象列表”
|
||||
- `api/migrations/sync_schema_to_models.sql` 在这段提交区间没有新增迁移内容
|
||||
|
||||
因此:
|
||||
|
||||
- 不需要新增 SQL migration
|
||||
- 不需要执行结构性数据迁移
|
||||
|
||||
## 图片功能判断
|
||||
|
||||
### `MEMOIR_IMAGE_ENABLED` 不是“全功能总开关”
|
||||
|
||||
这个开关能控制的是:
|
||||
|
||||
- 是否初始化待生成图片资产
|
||||
- 是否派发 `generate_chapter_images` 任务
|
||||
- 是否在读取章节时过滤掉未完成图片状态
|
||||
|
||||
这个开关不能完全关闭的内容:
|
||||
|
||||
- 章节正文里的图片占位符注入逻辑仍会存在
|
||||
- 已完成图片仍可能继续被返回和渲染
|
||||
- 章节接口仍会进入图片归一化逻辑
|
||||
- PDF 导出仍会处理已完成图片
|
||||
|
||||
### 旧 `chapters.images` 数据兼容性
|
||||
|
||||
历史文档里 `images` 被定义为“图片 URL 列表”,但当前代码要求每个元素都具备至少以下字段:
|
||||
|
||||
- `placeholder`
|
||||
- `description`
|
||||
|
||||
否则在归一化时会被过滤掉。
|
||||
|
||||
结论:
|
||||
|
||||
- 如果必须保留历史旧图,需要额外做读兼容或数据修复
|
||||
- 如果业务允许丢弃历史旧图,则这项不再构成上线阻塞
|
||||
|
||||
### 当前推荐策略
|
||||
|
||||
结合当前讨论结果,推荐采用以下上线策略:
|
||||
|
||||
1. 允许丢弃历史旧图
|
||||
2. 生产环境先保持 `MEMOIR_IMAGE_ENABLED=false`
|
||||
3. 先完成主链路上线
|
||||
4. 等生产 COS / Liblib / worker 验证完成后,再单独开启图片能力
|
||||
|
||||
这样做的好处:
|
||||
|
||||
- 不需要补兼容代码
|
||||
- 不需要回填旧数据
|
||||
- 能把风险集中在“新生成图片”而不是“历史数据”
|
||||
|
||||
## 生产环境配置判断
|
||||
|
||||
### 已具备的条件
|
||||
|
||||
- `Dockerfile` 会安装新的 Python 依赖,包括 `cos-python-sdk-v5`
|
||||
- `docker-compose.yml` 已包含 `api` 和 `celery-worker`
|
||||
- `api/.env.production` 已经包含图片链路需要的 `LIBLIB_*` 和 `TENCENT_COS_*` 配置项
|
||||
|
||||
### 仍需确认的点
|
||||
|
||||
- `TENCENT_COS_BUCKET` 和 `TENCENT_COS_BASE_URL` 是否为真正的生产资源
|
||||
- API 镜像和 Celery worker 是否会同步升级
|
||||
- 部署时是否一定会基于最新 `requirements.txt` 重新构建镜像
|
||||
|
||||
## 当前建议的上线结论
|
||||
|
||||
### 可以进入生产的前提
|
||||
|
||||
满足以下条件时,可以作为稳妥方案进入生产:
|
||||
|
||||
1. 接受丢弃历史旧图
|
||||
2. 保持 `MEMOIR_IMAGE_ENABLED=false`
|
||||
3. 使用最新镜像同时部署 `api` 与 `celery-worker`
|
||||
4. 确认 COS 配置不是误填开发资源
|
||||
|
||||
### 不建议直接开启图片功能的场景
|
||||
|
||||
如果满足以下任一情况,建议不要在本次发版里直接启用图片生成:
|
||||
|
||||
- 生产 COS bucket 尚未确认
|
||||
- Liblib 凭证未经生产验证
|
||||
- Celery worker 不会同步升级
|
||||
- 希望保留历史旧图但尚未做兼容或数据修复
|
||||
|
||||
## 最短上线检查单
|
||||
|
||||
发版前至少确认以下 5 项:
|
||||
|
||||
1. `api/.env.production` 中 `MEMOIR_IMAGE_ENABLED` 是否符合本次上线策略
|
||||
2. `TENCENT_COS_BUCKET` / `TENCENT_COS_BASE_URL` 是否为生产资源
|
||||
3. `api` 和 `celery-worker` 是否会使用同一版新镜像
|
||||
4. 镜像是否会基于最新 `requirements.txt` 重建
|
||||
5. 团队是否明确接受“历史旧图可能消失”
|
||||
|
||||
## 建议的发布策略
|
||||
|
||||
推荐分两步:
|
||||
|
||||
### 第一步:保守上线
|
||||
|
||||
- 发布当前代码
|
||||
- `MEMOIR_IMAGE_ENABLED=false`
|
||||
- 观察 API、WebSocket、章节读取、PDF 导出是否稳定
|
||||
|
||||
### 第二步:功能放量
|
||||
|
||||
- 确认 COS / Liblib / worker 正常
|
||||
- 再将 `MEMOIR_IMAGE_ENABLED=true`
|
||||
- 仅对新生成章节启用图片功能
|
||||
Reference in New Issue
Block a user