实现下单任务网关与本地 worker

按 docs/order-gateway.md 落地:第三个部署单元 app.gateway(:31109)承担任务队列
+ 状态镜像;本地 worker 在 app.trading.worker 内,按 RAKUTEN_ORDER_GATEWAY_URL
决定是否启动。规格 §5 最关键约束已守:租约过期绝不自动重投,恢复只能 reclaim,
worker 收到 lease_count>1 时先核对站点订单。

站点交互(加购/下单/付款/订单列表反查)按规格 §10 留接口缝,site_interact.py
全部 NotImplementedError,verify.py 恒返回 unknown——等真实账号实测后再填,
不写猜测的提交逻辑。

310 个测试全绿,覆盖规格 §9 验收清单 12 条;架构测试守住三方互不 import。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-27 16:25:20 +08:00
co-authored by Claude Opus 4.6
parent 91bfab7196
commit 07107094a7
35 changed files with 4342 additions and 62 deletions
+39 -9
View File
@@ -1,6 +1,7 @@
# 本仓库出个服务,共用这一份配置:
# 本仓库出个服务,共用这一份配置:
# 抓取服务 python -m app.scraping.main —— 匿名、无状态、可多开实例
# 交易服务 python -m app.trading.main —— 带账号登录态、有状态,只能单实例
# 下单任务网关 python -m app.gateway.main —— 任务队列 + 状态镜像,只能单实例
# 各自只读自己那部分,下面按用途分组标注。
# ---- 抓取服务监听地址,通常本地用 127.0.0.1,容器/服务器用 0.0.0.0 ----
@@ -11,6 +12,10 @@ RAKUTEN_APP_PORT=31107
RAKUTEN_TRADING_HOST=0.0.0.0
RAKUTEN_TRADING_PORT=31108
# ---- 下单任务网关监听地址(部署在服务器侧;本地 worker 出站长轮询取任务)----
RAKUTEN_GATEWAY_HOST=0.0.0.0
RAKUTEN_GATEWAY_PORT=31109
# 运行环境:dev / prod / test
RAKUTEN_APP_ENV=dev
@@ -56,14 +61,6 @@ RAKUTEN_PROXY_USERNAME=
# 代理密码(如代理需要认证则填写)
RAKUTEN_PROXY_PASSWORD=
# ---- 以下仅交易服务使用 ----
# 人工登录后落盘的 cookie 目录(相对项目根目录)。
# 里面是可直接冒充账号的凭据,已在 .gitignore 排除,不要提交、不要外传。
RAKUTEN_AUTH_STATE_DIR=.auth
# 下单金额上限(日元):实际应付超过该值直接拒绝提交,防止解析出错或页面改版
# 导致买到远超预期的订单。设为 0 表示不设上限(不建议)。
RAKUTEN_ORDER_MAX_TOTAL_YEN=30000
# ---- OpenTelemetry traces(可选;默认关闭)----
# 启用后把抓取-解析链路以 span 导出到 OTLP/HTTP endpoint,
# 用于排查"抓到的内容为什么解析不出预期字段"。
@@ -76,3 +73,36 @@ RAKUTEN_OTEL_SERVICE_NAME=
RAKUTEN_OTEL_HEADERS=
# 失败 HTML 快照上限字节(默认 2MB,超出截断并标注 truncated=true)
RAKUTEN_OTEL_SNAPSHOT_MAX_BYTES=2000000
# ---- 以下仅交易服务使用 ----
# 人工登录后落盘的 cookie 目录(相对项目根目录)。
# 里面是可直接冒充账号的凭据,已在 .gitignore 排除,不要提交、不要外传。
RAKUTEN_AUTH_STATE_DIR=.auth
# 下单金额上限(日元):实际应付超过该值直接拒绝提交,防止解析出错或页面改版
# 导致买到远超预期的订单。设为 0 表示不设上限(不建议)。
RAKUTEN_ORDER_MAX_TOTAL_YEN=30000
# ---- 以下仅下单任务网关使用 ----
# 任务队列 SQLite 文件路径(相对项目根目录)。务必放在持久化卷上,丢了等于
# 丢了一批下单任务。详见 docs/order-gateway.md。
RAKUTEN_GATEWAY_DB_PATH=data/gateway.db
# 任务租约 TTL(秒)。worker 领取后必须在此时间内首次 report 或 renew,否则
# 任务被置为 stale(**绝不自动重投**,需要人工 reclaim)。
RAKUTEN_LEASE_TTL_SECONDS=300
# 长轮询单次最长挂起秒数。worker 端 wait 参数会被夹到这个上限。
RAKUTEN_LEASE_MAX_WAIT_SECONDS=60
# worker 心跳超时阈值(秒)。超过即视为失联,/health 报 degraded。
RAKUTEN_WORKER_OFFLINE_ALERT_SECONDS=300
# ---- 以下仅交易服务内的下单 worker 使用 ----
# 网关 URL。**留空则不启动 worker**,交易服务只跑登录态接口。
# 部署形态:本地机(NAT 后无公网入口)通过出站长轮询从这里领任务。
RAKUTEN_ORDER_GATEWAY_URL=
# worker 标识。同一时间只能有一个 worker 持有 lease,留空时取主机名。
RAKUTEN_WORKER_ID=
# 本地订单 SQLite 文件路径(执行事实的权威记录)。
RAKUTEN_TRADING_DB_PATH=data/trading.db
# 页面证据目录(HTML 快照 + 截图 + meta.json,按 task_id 分子目录)。
RAKUTEN_EVIDENCE_DIR=data/evidence
# 抓取服务基地址。worker 需要商品数据(加购用 purchase 块)时出站请求这里。
RAKUTEN_SCRAPER_BASE_URL=