Skip to content

Commit f13d8af

Browse files
committed
Targeting readme
1 parent c12432a commit f13d8af

1 file changed

Lines changed: 129 additions & 0 deletions

File tree

targeting-engine/README.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# targeting-engine
2+
3+
A generic, zero-dependency rule evaluation engine extracted from the Split Java SDK. Given a parsed `TargetingRule` and a user key, it deterministically returns a treatment.
4+
5+
## Maven Dependency
6+
7+
```xml
8+
<dependency>
9+
<groupId>io.split.client</groupId>
10+
<artifactId>targeting-engine</artifactId>
11+
<version>4.18.3</version>
12+
</dependency>
13+
```
14+
15+
Requires Java 8+. No runtime dependencies.
16+
17+
## Usage
18+
19+
### 1. Implement `EvaluationContext`
20+
21+
The engine delegates two concerns back to the host application via `EvaluationContext`:
22+
23+
```java
24+
public class MyEvaluationContext implements EvaluationContext {
25+
26+
// Called for DependencyMatcher and PrerequisitesMatcher
27+
@Override
28+
public EvaluationResult evaluate(String matchingKey, String bucketingKey,
29+
String ruleName, Map<String, Object> attributes) {
30+
return myEngine.getTreatment(matchingKey, bucketingKey, ruleName, attributes);
31+
}
32+
33+
// Called for UserDefinedSegmentMatcher
34+
@Override
35+
public boolean isInSegment(String segmentName, String key) {
36+
return mySegmentStorage.isInSegment(segmentName, key);
37+
}
38+
39+
// Called for RuleBasedSegmentMatcher
40+
@Override
41+
public boolean isInRuleBasedSegment(String segmentName, String key,
42+
String bucketingKey,
43+
Map<String, Object> attributes) {
44+
return myRuleBasedSegmentEvaluator.isIn(segmentName, key, bucketingKey, attributes);
45+
}
46+
}
47+
```
48+
49+
### 2. Build a `TargetingRule`
50+
51+
`TargetingRule` contains only the fields needed for evaluation. Metadata (name, configurations, flag sets, etc.) belongs in the calling SDK's domain model.
52+
53+
```java
54+
List<Condition> conditions = List.of(
55+
new Condition(
56+
ConditionType.ROLLOUT,
57+
CombiningMatcher.of(new AllKeysMatcher()), // match everyone
58+
List.of(new Partition("on", 50), new Partition("off", 50)),
59+
"default rule"
60+
)
61+
);
62+
63+
TargetingRule rule = new TargetingRule(
64+
123456, // seed
65+
false, // killed
66+
"off", // defaultTreatment
67+
conditions,
68+
100, // trafficAllocation (0–100)
69+
654321, // trafficAllocationSeed
70+
2, // algo: 2 = MurmurHash3 (recommended), 1 = legacy
71+
null // prerequisites (List<Prerequisite> or null)
72+
);
73+
```
74+
75+
### 3. Evaluate
76+
77+
`TargetingEngineImpl` is stateless — create once, reuse across threads.
78+
79+
```java
80+
TargetingEngine engine = new TargetingEngineImpl();
81+
82+
EvaluationResult result = engine.evaluate(
83+
"user-123", // matchingKey
84+
null, // bucketingKey — null means use matchingKey
85+
rule,
86+
Map.of("plan", "pro"), // attributes — may be null
87+
context
88+
);
89+
90+
result.treatment // "on" | "off" | ...
91+
result.label // EvaluationLabels constant (e.g. "default rule")
92+
```
93+
94+
## Evaluation Labels
95+
96+
| Label constant | When returned |
97+
|---|---|
98+
| `EvaluationLabels.KILLED` | Rule is killed; `defaultTreatment` is returned |
99+
| `EvaluationLabels.PREREQUISITES_NOT_MET` | A prerequisite flag returned the wrong treatment |
100+
| `EvaluationLabels.NOT_IN_SPLIT` | User fell outside traffic allocation |
101+
| `EvaluationLabels.DEFAULT_RULE` | No condition matched; last condition applied |
102+
103+
Additional labels (`DEFINITION_NOT_FOUND`, `EXCEPTION`, `UNSUPPORTED_MATCHER`, `NOT_READY`) are set by the calling SDK, not by the engine.
104+
105+
## Data Model
106+
107+
| Class | Role |
108+
|---|---|
109+
| `TargetingRule` | Full rule definition (seed, conditions, traffic allocation, prerequisites) |
110+
| `Condition` | One targeting condition (`WHITELIST` or `ROLLOUT`) |
111+
| `Partition` | `(treatment, size%)` pair within a condition |
112+
| `Prerequisite` | Dependency on another rule's treatment |
113+
| `CombiningMatcher` | AND-combines a list of `AttributeMatcher`s |
114+
| `AttributeMatcher` | Extracts one attribute then delegates to a `Matcher` |
115+
116+
## Available Matchers
117+
118+
`AllKeysMatcher`, `WhitelistMatcher`, `EqualToMatcher`, `BetweenMatcher`, `BooleanMatcher`,
119+
`ContainsAnyOfMatcher`, `StartsWithAnyOfMatcher`, `EndsWithAnyOfMatcher`, `RegularExpressionMatcher`,
120+
`EqualToSemverMatcher`, `BetweenSemverMatcher`, `GreaterThanOrEqualToSemverMatcher`,
121+
`LessThanOrEqualToSemverMatcher`, `InListSemverMatcher`,
122+
`ContainsAllOfSetMatcher`, `ContainsAnyOfSetMatcher`, `EqualToSetMatcher`, `PartOfSetMatcher`,
123+
`UserDefinedSegmentMatcher`, `RuleBasedSegmentMatcher`, `DependencyMatcher`
124+
125+
## Building
126+
127+
```bash
128+
mvn -pl :targeting-engine clean install
129+
```

0 commit comments

Comments
 (0)