Ranking
Selection policy, specificity distance, preference order, and tie-breaking
Separation of Concerns
The system distinguishes two phases:
- Dispatch Validity — Is this provider legal for this request? (see Dispatch)
- Ranking — Among valid providers, which should be selected?
Ranking applies ONLY to dispatch-valid providers. Never rank before validating.
The Valid Set
Given a request $r$, define the valid set:
Ranking is a total order over $\text{Valid}(r)$.
Specificity Distance
Definition
For a provider $p$ and request $r$:
Where $\text{spec}_C$ is Cap URN specificity (see Specificity).
Interpretation
| Distance | Meaning | Provider Relationship |
|---|---|---|
dist = 0 |
Equivalent | Provider matches request exactly |
dist > 0 |
Refinement | Provider is more specific |
dist < 0 |
Fallback | Provider is more generic |
Preference Order
Standard Policy
The default ranking policy prefers:
- Exact match (
dist = 0) — most preferred - Refinement (
dist > 0) — provider specializes request - Fallback (
dist < 0) — provider is generic, last resort
Within each category, prefer smaller absolute distance.
Formal Ordering
For providers $a$ and $b$ in $\text{Valid}(r)$:
- $\text{dist}(a,r) \geq 0$ and $\text{dist}(b,r) < 0$ — a is refinement, b is fallback
- Both refinements, a closer: $\text{dist}(a,r) \geq 0 \land \text{dist}(b,r) \geq 0 \land \text{dist}(a,r) < \text{dist}(b,r)$
-
Both fallbacks, a closer: $$\text{dist}(a,r) < 0 \land \text{dist}(b,r) < 0 \land \text{dist}(a,r) < \text{dist}(b,r) $$
Simplified Rule
preferred = min(valid_providers, key=ranking_key)
def ranking_key(p, r):
d = dist(p, r)
if d >= 0:
return (0, d) # refinement tier, prefer smaller positive
else:
return (1, -d) # fallback tier, prefer smaller negative
Tie-Breaking
When multiple providers have the same distance:
Default Policy
First registered wins — the provider that was registered first is selected.
Subsystem Policies
| Subsystem | Policy |
|---|---|
| UrnMatcher | First by specificity, then by registration order |
| CapMatrix | Strict > comparison (no ties possible) |
| CapBlock | Strict > comparison (no ties possible) |
| RelaySwitch | First registered wins |
Avoiding Ties
Design caps to avoid ties by ensuring distinct specificities:
- Add distinguishing tags
- Use consistent naming conventions
- Register more specific caps before generic ones
Examples
Exact Match Preferred
Request: cap:in=media:pdf;op=extract;out=media:object
spec = 3
Valid providers:
A: cap:in=media:pdf;op=extract;out=media:object spec=3, dist=0
B: cap:in=media:pdf;op=extract;out=media:object;v=2 spec=4, dist=+1
C: cap:op=extract spec=1, dist=-2
Ranking: A (dist=0) ≺ B (dist=+1) ≺ C (dist=-2)
Selected: A
Refinement When No Exact Match
Request: cap:op=convert
spec = 1
Valid providers:
A: cap:in=media:pdf;op=convert;out=media:html spec=3, dist=+2
B: cap:in=media:image;op=convert;out=media:png spec=3, dist=+2
C: cap:op=convert spec=1, dist=0
Ranking: C (dist=0) ≺ {A, B} (dist=+2, tie)
Selected: C
If C not available:
{A, B} tied at dist=+2
Selected: First registered of A or B
Fallback Only
Request: cap:in=media:pdf;v=2.0;op=extract;out=media:object;format=json
spec = 5
Valid providers:
A: cap:in=media:pdf;op=extract;out=media:object spec=3, dist=-2
B: cap:op=extract spec=1, dist=-4
Ranking: A (dist=-2) ≺ B (dist=-4)
Selected: A (closer to request despite being less specific)
Preferred Cap Hints
User Preference
The system supports an optional preferred cap hint:
RelaySwitch::route_request(request, preferred_cap: Option<&CapUrn>)
When preferred_cap is provided:
- Find valid providers via
is_dispatchable - Among valid providers, check if any is
is_equivalentto preferred - If found, select it regardless of specificity ranking
- Otherwise, fall back to normal ranking
Use Cases
- User explicitly requests a specific capability version
- Configuration specifies a particular provider
- Testing with known handler
Properties
Determinism
Given the same request, set of registered providers, and registration order — the selected provider is deterministic.
Stability
Adding a new provider P:
- If P is not in
Valid(r), selection unchanged - If P is in
Valid(r), P may be selected only if it ranks higher
Monotonicity
If provider $p$ is selected for request $r$, then $p$ remains selected for any request $r'$ where $r' \preceq r$ and $\text{Dispatch}(p, r')$ still holds.
Implementation Notes
For small provider sets, linear scan is sufficient:
fn select_best(providers: &[CapUrn], request: &CapUrn) -> Option<&CapUrn> {
let request_spec = request.specificity();
providers.iter()
.filter(|p| p.is_dispatchable(request))
.min_by_key(|p| {
let dist = p.specificity() as isize - request_spec as isize;
if dist >= 0 {
(0, dist)
} else {
(1, -dist)
}
})
}
For frequently queried requests, cache:
- The valid set
Valid(r) - The sorted ranking
- The selected provider
Invalidate on provider registration/unregistration.
Relationship to is_comparable
The is_comparable predicate from Predicates is sometimes used for discovery but NOT for ranking:
Comparable providers may not be dispatchable. Always check is_dispatchable first.
Summary
| Concept | Definition |
|---|---|
| Valid set | $\{ p \mid \text{Dispatch}(p, r) \}$ |
| Distance | $\text{spec}_C(p) - \text{spec}_C(r)$ |
| Preference | Exact (0) > Refinement (+) > Fallback (-) |
| Tie-break | First registered (default) |
Ranking is policy, not semantics. The dispatch predicate defines validity; ranking determines selection among valid options.