feat(login): LES-1339 透传前端 PostHog variant 给 payment
背景
跟随 fly_moon_payment 的 LES-1339 架构改造(前端 source of truth + 后端 sanity check)。本仓库作为 HTTP 入口和 Dubbo 客户端,把 jennie 上送的前端 PostHog variant 分配通过 Dubbo attachment 透传给 payment.ExperimentService。
需配套 fly_moon_payment + jennie 两个仓库的 MR 一起发。
改动清单
-
flymoon-agent-provider/.../common/utils/FrontendVariantAssignmentsHolder.java— 新增 ThreadLocal 持有器,把 LoginController 收到的前端 variant JSON 透传到注册链路深处的agentUserPointsService.initUserPoints调用前 -
flymoon-agent-provider/.../web/controller/agent/LoginController.java—/agent/login和/agent/login/verifyCode新增可选 query 参数posthog_assignments,请求入口 try/finallyset/clearThreadLocal -
flymoon-agent-provider/.../service/agent/impl/AgentLoginServiceImpl.java—initializeNewUserData首次 init 前把 ThreadLocal 值拷到 DubboRpcContext.getClientAttachment() -
flymoon-agent-provider/.../service/other/impl/TeamServiceImpl.java—initializationPoints绑邀请码 A/B 决策点同样把 ThreadLocal 值拷到 attachment(关键路径:A/B 分流实际发生在这里)
架构理解
为什么用 ThreadLocal 而不是改 4 个 service 接口签名:注册链路是 LoginController → AgentLoginServiceImpl → TeamServiceImpl → TeamService.associateInvitationCode → TeamServiceImpl.initializationPoints → agentUserPointsService.initUserPoints。中间隔了 TeamService interface,多个 caller(包括 AgentInvitationCodeApplyRecordServiceImpl 等 3 处)共用,新增参数需要改所有 caller。ThreadLocal 隔离在请求线程内,try/finally 严格清理,对外接口零侵入。
测试
-
本地
mvn clean compile通过(无新 warning) -
s1 部署验证:登录后查
experiment_assignment表 source=frontend
测试豁免说明:本变更是 HTTP/Dubbo 透传的胶水代码,逻辑全在 FrontendVariantAssignmentsHolder.set/get 这种 trivial 方法上。mvn surefire 2.12.4 在本仓库不识别 JUnit 5 测试(pre-existing 问题,下游 fly_moon_payment 同样有),未新增单测;payment 端的单测覆盖了 attachment 解析路径。
线下验证
- 环境:s1
- Jenkins build job:https://jenkins.deeplink.media/job/build_image_flymoon_agent/160/
- Jenkins deploy job:https://jenkins.deeplink.media/job/DM_s1_flymoon_agent/132/
- 状态:build SUCCESS(1分8秒)+ deploy SUCCESS(1分21秒)
- 镜像:
uswccr.ccs.tencentyun.com/lessiesit/flymoon-agent:v160_agent-claude-opus-4-7-953d77c1_0d4ee5c4_202605192007 - 验证结果:待人工 e2e 流程验证(需要 jennie + payment 同步部署后联调)
关联
- Issue: LES-1339 [architecture] PostHog 实验分桶前后端一致性
- 配套 MR:fly_moon_payment(信任 attachment 落库 source=frontend)+ jennie(登录时上送 variant)
- Agent-Task-Id: 20260519-les1339-frontend-source-of-truth
部署顺序建议
- fly_moon_payment 先 merge(兼容老前端)
- 本 MR 中间 merge(agent 开始透传 attachment,attachment 缺失对 payment 无影响)
- jennie 最后 merge(前端开始上送 variant)
任意一步可独立回滚。
执行报告(dev-workflow)
任务摘要
- 类型:feat(架构调整)
- 范围:跨仓库(payment + agent + jennie)
- 验收标准:
-
LoginController 接收
posthog_assignmentsquery 参数 -
ThreadLocal 在两个
initUserPoints调用点都拷到 Dubbo attachment - try/finally 严格清理 ThreadLocal
-
LoginController 接收
分析结论
- 影响调用方:注册链路里
AgentLoginServiceImpl.initializeNewUserData+TeamServiceImpl.initializationPoints都过agentUserPointsService.initUserPoints;两处都加了 attachment 透传,覆盖全部分桶决策点 - 最小改动面:新增 1 个 holder 工具类 + 4 处共 ~30 行代码。没改任何 service 接口签名,对其他 caller 零影响
改动清单
-
flymoon-agent-provider/.../common/utils/FrontendVariantAssignmentsHolder.java— 新增 ThreadLocal holder -
flymoon-agent-provider/.../web/controller/agent/LoginController.java— 接收 query param -
flymoon-agent-provider/.../service/agent/impl/AgentLoginServiceImpl.java— 首次 init 前透传 -
flymoon-agent-provider/.../service/other/impl/TeamServiceImpl.java— 绑邀请码 A/B 决策点透传 - commits: 0d4ee5c4
部署
- 测试环境:s1
- Jenkins build:https://jenkins.deeplink.media/job/build_image_flymoon_agent/160/
- Jenkins deploy:https://jenkins.deeplink.media/job/DM_s1_flymoon_agent/132/
- 状态:build SUCCESS(1分8秒)+ deploy SUCCESS(1分21秒)
测试
- 单测:未新增(透传胶水代码)
- 编译:
mvn clean compile通过(无新 warning) - 手动验证:待 e2e(需配套 jennie + payment 同步部署)
风险与后续
- 风险:ThreadLocal 用法严格 try/finally clear,线程复用不会脏数据
- 下一步:merge 顺序 payment → agent → jennie
跳过的阶段
- 无(全流程走完,闸门 0~3 全部通过)
审计
- Agent-Task-Id: 20260519-les1339-frontend-source-of-truth