fix(canary): team-CS 分流改为有状态均衡随机,保证 staging 总量份额 / stateful balanced shunting guarantees staging share - #65
Open
370025263 wants to merge 1 commit into
Open
fix(canary): team-CS 分流改为有状态均衡随机,保证 staging 总量份额 / stateful balanced shunting guarantees staging share#65370025263 wants to merge 1 commit into
370025263 wants to merge 1 commit into
Conversation
fix(canary): stateful balanced shunting for team-CS to guarantee staging share 无状态 pick_side 在 client 基数很小时(board6 仅 3 个 worker)会把所有 client 哈希到 main,staging 流量饿死为 0,灰度永远拿不到 UX 样本。 新增 CanaryRouter:按 skill 维护 client→side 账本,新 client 落到"让运行 比例最贴近 probability"的一侧(平局随机),把 staging 份额锁进总量而非听天 由命。同 client 在同一 staging 版本内 side 钉死(轨迹一致性);staging sha 或 probability 变化则重置账本、重新均衡。仅用于 team-CS manifest 路径 (client 基数小);高基数 traj/window 路径继续用 pick_side——大数定律下 无状态哈希天然均衡。 The stateless pick_side hash starves staging to zero traffic when the shunt key cardinality is tiny (board6 has only 3 workers): all three can hash to main, so the canary never collects a single staging UX sample. CanaryRouter keeps a per-skill client→side ledger and assigns each new client to the side that keeps the running ratio closest to `probability` (random tie-break), baking staging's share into the total instead of leaving it to chance. A client stays on its assigned side for the lifetime of a staging version; the ledger resets when the staging sha or probability changes. Only the team-CS manifest path (few clients) is switched; high-cardinality traj/window paths keep pick_side, which balances naturally by the law of large numbers. - canary.py: +CanaryRouter (thread-safe, reset, _balanced_side) - skill_manifest.py: _resolve_slot uses module-level _ROUTER.assign - client_registry.py: docstring pick_side -> CanaryRouter.assign - tests: balanced-share regression (3 clients p=0.5 => >=1 staging), per-client lock, sha/probability reset, ratio tracking
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题 / Problem
team-CS manifest 路径用无状态
pick_side(client_id, skill_name, probability)决定灰度 side。当 client 基数很小(Xarena board6 仅 3 个 worker)时,3 次 0.5 概率的独立哈希有 1/8 概率全落 main,staging 流量饿死为 0,灰度永远拿不到 UX 样本,canary 永远停在waiting。实测:sub63 的 3 个 worker 对唯一 skill
openpyxl-excel-automation的 hash 全 >0.5,全部固定 main →staging promoted=0 / ux side_counts={'main':66}。The stateless
pick_sidehash in the team-CS manifest path starves staging to zero traffic when the shunt-key cardinality is tiny: with only 3 workers at p=0.5, there is a 1/8 chance all three hash to main, so the canary never collects a single staging UX sample and stays stuck inwaitingforever.Observed on sub63: all 3 workers hashed >0.5 for the sole skill
openpyxl-excel-automation→staging promoted=0,ux side_counts={'main': 66}.方案 / Fix
新增
CanaryRouter:按 skill 维护 client→side 账本,新 client 落到"让运行 main/staging 比例最贴近probability"的一侧(平局随机),把 staging 份额锁进总量而非听天由命。不靠调高 probability。pick_side(大数定律下天然均衡)Add
CanaryRouter: a per-skill client→side ledger that assigns each new client to the side keeping the running ratio closest toprobability(random tie-break), baking staging's share into the total instead of leaving it to chance — no probability bump.验证 / Verification
tests/test_canary.py: 均衡份额回归(3 client p=0.5 ⇒ 1~2 staging,200 次试验永不 0)、p=0.2/5-client 恰好 1 staging、100-client 比例误差 ≤2%、per-client 锁、sha/prob 重置tests/test_team_skill_manifest.py: 3 worker + 唯一 staging skill ⇒ ≥1 staging(饿死 bug 回归测试)