Files
life-echo/api/app/core/error_codes.py
Sully 53e0065e3e refactor(api): TOML 配置 SSOT、统一错误契约、Auth/事务加固与可观测性 (#33)
配置 SSOT(TOML + .env)
统一错误契约
Auth 与事务边界
Redis / Celery 可靠性:业务 Redis(DB/0)与 Celery broker/backend(DB/1)显式拆分;连接池、sync client
可观测性(OpenTelemetry + LGTM)
2026-05-22 13:44:50 +08:00

153 lines
3.9 KiB
Python
Raw Permalink 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.
"""
统一错误码注册表(供 OpenAPI 文档与客户端分支参考)。
HTTP 错误响应体:``{ "error_code": str, "message": str, "request_id": str }``
"""
from __future__ import annotations
from typing import TypedDict
class ErrorCodeEntry(TypedDict):
code: str
http_status: int
domain: str
description: str
# ── 全局 / core AppError ─────────────────────────────────────
CORE_ERROR_CODES: list[ErrorCodeEntry] = [
{
"code": "BAD_REQUEST",
"http_status": 400,
"domain": "core",
"description": "请求无效(通用)",
},
{
"code": "AUTHENTICATION_FAILED",
"http_status": 401,
"domain": "core",
"description": "未认证或凭据无效",
},
{
"code": "FORBIDDEN",
"http_status": 403,
"domain": "core",
"description": "权限不足",
},
{
"code": "NOT_FOUND",
"http_status": 404,
"domain": "core",
"description": "资源不存在",
},
{
"code": "CONFLICT",
"http_status": 409,
"domain": "core",
"description": "资源冲突",
},
{
"code": "VALIDATION_ERROR",
"http_status": 422,
"domain": "core",
"description": "请求体验证失败",
},
{
"code": "QUOTA_EXCEEDED",
"http_status": 429,
"domain": "core",
"description": "配额已用尽",
},
{
"code": "RATE_LIMITED",
"http_status": 429,
"domain": "core",
"description": "请求频率超限(如 SMS 发送冷却)",
},
{
"code": "INTERNAL_ERROR",
"http_status": 500,
"domain": "core",
"description": "服务器内部错误",
},
{
"code": "PROVIDER_ERROR",
"http_status": 502,
"domain": "core",
"description": "外部服务异常(如短信发送失败)",
},
{
"code": "SERVICE_UNAVAILABLE",
"http_status": 503,
"domain": "core",
"description": "服务未配置或暂时不可用",
},
{
"code": "GATEWAY_TIMEOUT",
"http_status": 504,
"domain": "core",
"description": "网关超时",
},
]
# ── auth 领域AuthError────────────────────────────────────
AUTH_ERROR_CODES: list[ErrorCodeEntry] = [
{
"code": "PHONE_EXISTS",
"http_status": 400,
"domain": "auth",
"description": "手机号已注册",
},
{
"code": "EMAIL_EXISTS",
"http_status": 400,
"domain": "auth",
"description": "邮箱已注册",
},
{
"code": "INVALID_SMS_CODE",
"http_status": 400,
"domain": "auth",
"description": "短信验证码无效、过期或已使用",
},
{
"code": "WRONG_PASSWORD",
"http_status": 400,
"domain": "auth",
"description": "旧密码错误",
},
{
"code": "PHONE_TAKEN",
"http_status": 409,
"domain": "auth",
"description": "手机号已被其他账号占用",
},
{
"code": "REFRESH_TOKEN_REUSE",
"http_status": 401,
"domain": "auth",
"description": "刷新令牌在 grace 窗口外被重复使用或疑似盗用,全部会话已吊销",
},
]
# ── payment 领域PaymentError / order_service──────────────
PAYMENT_ERROR_CODES: list[ErrorCodeEntry] = [
{
"code": "PAYMENT_FAILED",
"http_status": 500,
"domain": "payment",
"description": "创建或处理支付订单失败",
},
]
ALL_ERROR_CODES: list[ErrorCodeEntry] = (
CORE_ERROR_CODES + AUTH_ERROR_CODES + PAYMENT_ERROR_CODES
)
ERROR_CODE_ENUM: list[str] = sorted({e["code"] for e in ALL_ERROR_CODES})