feat(routing): make volume-split selection deterministic per payment - #406
Open
prajjwalkumar17 wants to merge 3 commits into
Open
feat(routing): make volume-split selection deterministic per payment#406prajjwalkumar17 wants to merge 3 commits into
prajjwalkumar17 wants to merge 3 commits into
Conversation
Volume splits rolled rand::thread_rng() on every evaluation, so the SDK's concurrent init calls (payment-methods list, sdk-config, session tokens) could each pick a different winner for the same payment - skewing the configured split and letting a wallet's session token disagree with the connector the payment later confirms on. Seed the split with the request's payment_id when present: djb2 slot over the cumulative weights, walked in declaration order (the same scheme the A/B arm assignment already uses, and byte-identical with Hyperswitch's seeded split so both engines pick the same winner). Requests without a payment_id keep the random roll. Winner-first ordering and the remaining declaration order are unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # src/decider/gatewaydecider/ab_test/preview.rs # src/euclid/interpreter.rs
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.
Pairs with hyperswitch PR: juspay/hyperswitch#13956
Why
Volume splits roll
rand::thread_rng()on every evaluation. One checkout mount firesthree concurrent evaluating calls (payment-methods list, sdk-config, session tokens),
so the same payment could get
connector Afrom one call andconnector Bfromanother — skewing the configured split and letting a wallet's session token disagree
with the connector the payment later confirms on.
What
sample_split_winner_first(and everything above it:perform_volume_split,perform_volume_split_priority,evaluate_output,eval_program) takes anoptional seed; the evaluate handlers pass the request's
payment_id(single andbatch entries alike, plus the A/B preview arms).
order — the exact scheme
ab_test::assign_arm/ the A/B static-arm evaluatoralready use, and byte-identical with Hyperswitch's seeded split (cross-repo
test vector
djb2("pay_nZwbogscgFwIanlGnUxw") = 10501740297535541692asserted inboth repos).
payment_idkeep the random roll. Winner-first ordering andthe tail's declaration order are unchanged.
Notes for reviewers
of the list so failure-retries still fall through to the next connector.
payment agree exactly, so volume-split rules no longer need diff-suppression in
shadow comparisons (HS-side follow-up).
ids, zero-weight guard, unseeded fallback. 423 lib tests + clippy clean.
🤖 Generated with Claude Code