ac8935c641
WeWorkFinanceSdk 是 Go c-shared 库、自带 Go runtime, 嵌进 app-server(uvicorn)后台线程跑会 segfault 把主进程带崩(2026-07-17 实测:开 worker 后 app-server core-dump 每 5s 循环)。改成 轮询搬到【独立进程】(Go runtime 独占进程+主线程, 崩了 systemd 只重启本进程、不动 app-server), 拉到卡片/图后 POST app-server 内部端点打信号(set_pending 在 app-server 进程内存, 心跳才 pop 得到)。 - 删 app/core/wx_finance_worker.py(进程内 worker), main lifespan 不再起它 - 新增内部端点 POST /internal/wx-finance/pending(X-Internal-Secret)→ set_pending(复用现有内部端点范式) - 新增 scripts/wx_finance_poller.py(独立 poller:GetChatData 轮询→解密→weapp/image→POST 内部端点) - 新增 deploy/wx-finance-poller.service(独立 systemd 单元, 与 app-server 隔离) - config 加 WX_FINANCE_INTERNAL_URL(poller→app-server 内部地址, 默认 127.0.0.1:8770) - SDK 封装 wx_finance_sdk.py 原样复用(探针已验证 Init/GetChatData 通) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
59 lines
2.3 KiB
Python
59 lines
2.3 KiB
Python
"""会话存档独立 poller → app-server 的内部信号端点(server→server, 非客户端接口)。
|
|
|
|
会话存档轮询在【独立进程】跑(WeWorkFinanceSdk 是 Go c-shared 库, 嵌进 app-server 会 segfault
|
|
把主进程带崩, 见 scripts/wx_finance_poller.py)。poller 拉到美团卡片/截图后 POST 到这里, 由
|
|
app-server 打比价信号 —— set_pending 在 app-server 进程内存, 心跳才 pop 得到, 故必须回到本进程。
|
|
靠共享密钥头 X-Internal-Secret(== settings.INTERNAL_API_SECRET)校验;未配置 → 503。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import hmac
|
|
import logging
|
|
from typing import Annotated
|
|
|
|
from fastapi import APIRouter, Header, HTTPException, status
|
|
|
|
from app.core import wx_poc_signal
|
|
from app.core.config import settings
|
|
from app.schemas.wx_finance import WxFinancePendingIn, WxFinancePendingOut
|
|
|
|
logger = logging.getLogger("shagua.internal.wx_finance")
|
|
|
|
router = APIRouter(prefix="/internal", tags=["internal"])
|
|
|
|
|
|
def _check_secret(x_internal_secret: str | None) -> None:
|
|
"""共享密钥校验。未配置 → 503(挡裸奔);不匹配 → 401(常量时间比较)。"""
|
|
configured = settings.INTERNAL_API_SECRET
|
|
if not configured:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="internal api not configured",
|
|
)
|
|
if not x_internal_secret or not hmac.compare_digest(x_internal_secret, configured):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid internal secret"
|
|
)
|
|
|
|
|
|
@router.post(
|
|
"/wx-finance/pending",
|
|
response_model=WxFinancePendingOut,
|
|
summary="会话存档 poller 触发比价信号(独立进程→app-server, 打 set_pending)",
|
|
)
|
|
def wx_finance_pending(
|
|
payload: WxFinancePendingIn,
|
|
x_internal_secret: Annotated[str | None, Header()] = None,
|
|
) -> WxFinancePendingOut:
|
|
_check_secret(x_internal_secret)
|
|
device_id = settings.WX_POC_TEST_DEVICE_ID
|
|
if not device_id:
|
|
logger.warning("wx_finance pending: WX_POC_TEST_DEVICE_ID 未配置, 忽略信号")
|
|
return WxFinancePendingOut(ok=False)
|
|
wx_poc_signal.set_pending(device_id, payload.source)
|
|
logger.info(
|
|
"wx_finance PoC: 已给测试设备 %s 打比价信号 source=%s (触发=%s)",
|
|
device_id, payload.source, payload.kind,
|
|
)
|
|
return WxFinancePendingOut(ok=True)
|