-
Notifications
You must be signed in to change notification settings - Fork 6
Description
Problem
When a materialization record exists for the unit but has no variant for the matched rule (empty ruleToVariant), the Rust resolver sets materialization_matched = Some(false) and falls back to segment matching. If the segment targeting doesn't match (e.g. wrong country), the result is NO_SEGMENT_MATCH. Java falls through to hash-based bucket assignment and returns MATCH.
Rust behavior
confidence-resolver/src/lib.rs ~L1072-1128:
match materialization_context.has_rule_materialization(
read_materialization, &unit, &rule.name,
)? {
Some(false) => {
materialization_matched = Some(false); // <-- blocks fallthrough
if read_mode.materialization_must_match {
continue;
}
}
Some(true) => {
// ... try to select assignment from materialization
}
None => { ... }
}
if materialization_matched != Some(true) {
// falls back to segment_match, which may fail
materialization_matched = match self.segment_match(...) { ... };
}When has_rule_materialization returns Some(false) (unit is in materialization but no variant for this rule), Rust sets materialization_matched = Some(false). This forces segment matching. If the segment targeting fails (e.g. country mismatch), the rule is skipped → NO_SEGMENT_MATCH.
Java behavior
AccountResolver.java ~L287-369:
} else {
// Unit IS in materialization
// ... targeting check ...
if (materializationMatched) {
final Optional<String> variant = materializationInfo.getVariantForRule(rule.getName());
if (variant.isPresent()) {
// Use materialization variant
return variantMatch(...);
}
// variant is empty → falls through
}
}
// Falls through to segment matching + bucket assignment
if (!materializationMatched && !segmentMatches(...)) {
continue;
}
// Hash-based bucket assignment
final long bucket = Randomizer.getBucket(unit.get(), variantSalt, bucketCount);
matchedAssignmentOpt = spec.getAssignmentsList().stream()
.filter(variant -> Randomizer.coversBucket(variant, bucket))
.findFirst();When getVariantForRule() returns empty, Java does not set materializationMatched = false. It falls through to the hash-based bucket assignment, which uses the targeting key to compute a bucket and pick a variant. The !materializationMatched check passes because materializationMatched was set to true during the targeting check above, so segment matching is skipped entirely.
Affected spec tests
mat_matched_no_variant_for_rule