# 正念 APP（后端）

本目录为正念 APP 的后端服务（FastAPI），负责：

- 提供业务 API（情绪文案/卡片、用户配置、推送配置等）
- 支撑定时任务（推送、内容刷新等）
- 对接数据库与缓存（MySQL / Redis）

> 说明：当前 `server/` 目录仅包含说明文档，尚未初始化具体代码与依赖文件。本文档按“推荐工程形态”编写，等代码落地后只需把入口模块名与配置字段名对齐即可。

## 技术栈

- Python + FastAPI
- SQLAlchemy（建议 2.x，异步）+ MySQL 8.0
- Alembic（数据库迁移）
- Celery + Redis（任务调度/定时推送）
- Pydantic v2（数据校验）+ pydantic-settings（环境配置）
- pytest（测试）

## 本地开发

### 1. 环境要求

- Python：3.11+
- MySQL：8.0+

### 2. 创建虚拟环境

在 `server/` 目录下：

```bash
python -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
```

### 3. 安装依赖


- 方式 ：`requirements.txt`（示例）

```bash
pip install -r requirements.txt
```



## 配置（dev / prod）

推荐使用 `.env.dev` 与 `.env.prod`，由 `pydantic-settings` 读取。

### 1. 环境变量示例

在 `server/` 下创建 `.env.dev`（示例字段，可按代码中的 Settings 字段名调整）：

```dotenv
# 运行环境
APP_ENV=dev
APP_NAME=mindfulness-server
APP_HOST=0.0.0.0
APP_PORT=8000

# 数据库（推荐用统一的 DATABASE_URL，或拆分为 MYSQL_*）
DATABASE_URL=mysql+aiomysql://<用户名>:<密码>@<MySQL_HOST>:3306/mindfulness_dev?charset=utf8mb4
# MYSQL_HOST=127.0.0.1
# MYSQL_PORT=3306
# MYSQL_USER=root
# MYSQL_PASSWORD=password
# MYSQL_DB=mindfulness_dev

# Redis（缓存/任务队列）
REDIS_URL=redis://dev_user:devpassword@127.0.0.1:6379/0
最大的存储限制是256 请尽量少使用
# Celery（建议先只用 broker；如需结果存储请务必设置 TTL）
CELERY_BROKER_URL=redis://dev_user:devpassword@127.0.0.1:6379/0
# CELERY_RESULT_BACKEND=redis://dev_user:devpassword@127.0.0.1:6379/0

# 推送/第三方（按实际接入补充）
# PUSH_PROVIDER=expo
# EXPO_ACCESS_TOKEN=
```

`.env.prod` 同理，替换为生产环境地址与密钥即可。

### 1.1 MySQL 命名与 dev/pro 区分（约定）

- **生产库（prod）**：`mindfulness`
- **开发库（dev）**：`mindfulness_dev`

建议：

- **库名/表名/字段名**：统一小写 + 下划线（snake_case）
- **字符集**：统一 `utf8mb4`

`.env.dev` 指向 `mindfulness_dev`，`.env.prod` 指向 `mindfulness`：

```dotenv
# prod 示例
DATABASE_URL=mysql+aiomysql://<用户名>:<密码>@<MySQL_HOST>:3306/mindfulness?charset=utf8mb4
```

### 1.2 Redis：通过 ACL 限制 dev/pro 前缀访问

只启动 **一个 Redis 服务**，用 **ACL + key 前缀**隔离环境数据：

```text
# Dev 用户，只能访问 dev:* 前缀
user dev_user on >devpassword ~dev:* +@all

# Pro 用户，只能访问 pro:* 前缀
user pro_user on >propassword ~pro:* +@all
```

连接串示例（dev/pro 使用不同账号）：

```dotenv
# dev
REDIS_URL=redis://dev_user:devpassword@127.0.0.1:6379/0
CELERY_BROKER_URL=redis://dev_user:devpassword@127.0.0.1:6379/0

# prod
# REDIS_URL=redis://pro_user:propassword@127.0.0.1:6379/0
# CELERY_BROKER_URL=redis://pro_user:propassword@127.0.0.1:6379/0
```

重要约定：

- **应用写入 Redis 的 key 必须带前缀**：dev 环境使用 `dev:`，prod 环境使用 `pro:`
- **Celery 队列/键也建议带环境前缀**（例如队列名 `dev:push` / `pro:push`），避免同机多环境混用时相互影响

### 2. 配置加载约定（建议）

- 通过 `APP_ENV` 决定加载 `.env.dev` 或 `.env.prod`
- 代码中使用 `pydantic-settings` 定义 `Settings`，并集中在 `app/core/config.py`（仅建议命名）

## 启动服务（FastAPI）

> 下方入口模块名为示例：假设你的 FastAPI 实例位于 `app/main.py` 中的 `app` 变量。若实际路径不同，请自行替换。

```bash
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
```

启动后可访问：

- OpenAPI 文档：`/docs`
- ReDoc：`/redoc`

## 数据库迁移（Alembic）

> 若你采用 Alembic：建议把迁移脚本放在 `server/alembic/`，并在 `alembic.ini` 中配置数据库连接（或从环境变量读取）。

常用命令（示例）：

```bash
alembic revision --autogenerate -m "初始化表结构"
alembic upgrade head
```

## 任务调度（Celery + Redis）

> 下方入口模块名为示例：假设 Celery 实例位于 `app/worker.py` 中的 `celery_app` 变量。若实际路径不同，请自行替换。

启动 Worker（处理异步任务）：

```bash
celery -A app.worker:celery_app worker -l info
```

启动 Beat（定时任务调度，若你使用 celery beat）：

```bash
celery -A app.worker:celery_app beat -l info
```

## 运行测试（pytest）

```bash
pytest -q
```

## 推荐目录结构（建议）

> 仅为建议，便于后续协作与扩展。

```text
server/
  app/
    main.py               # FastAPI 入口（app = FastAPI()）
    core/
      config.py           # Settings（pydantic-settings）
      logging.py
    db/
      session.py          # 数据库会话/引擎
      models/             # ORM 模型
      migrations/         # （如不使用默认 alembic 目录，可自定义）
    api/
      v1/
        routes/
    tasks/
      push.py             # 推送相关任务
    worker.py             # Celery 入口（celery_app = Celery(...)）
  tests/
  README.md
```

## 常见问题

- **MySQL 连接报错/字符集问题**：建议统一使用 `utf8mb4`，并在连接串中带上 `charset=utf8mb4`。
- **Celery 无法连接 Redis**：检查 `CELERY_BROKER_URL` 与 Redis 是否可达、端口是否开放。