pulse-lets-go/docs/scoring.md

74 lines
2.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Scoring Engine
Вычисляет score (0..100) для каждой ноды. Ноды со score = -100 исключаются из роутинга.
## Lethal Conditions (score → -100)
Если хотя бы одно условие истинно — нода исключается:
If at least one is true — node is excluded from routing.
| Condition | Threshold |
|-----------|-----------|
| `status != "ok"` | Any status other than `ok` |
| Stale | > `stale_threshold_sec` (default 20s) |
| `active_calls >= max_calls` | 100% capacity used |
| `idle_cpu < idle_cpu_min` | < 5% |
| `call_failure_rate > call_failure_rate_lethal` | > 15% |
| `disabled == true` | Manual admin disable |
## Weighted Score (0..100)
```
call_score = clamp(100 - (active_calls / max_calls * 100), 0, 100)
load_score = clamp(100 - (load_avg * 50), 0, 100)
idle_score = clamp(idle_cpu, 0, 100)
fail_score = clamp(100 - call_failure_rate, 0, 100)
score = call_score × 0.40 +
load_score × 0.30 +
idle_score × 0.20 +
fail_score × 0.10
```
Weight defaults (configurable in `config.json`): call 40%, load 30%, idle 20%, fail 10%.
## Example
Node `pbx-01`: `active_calls=42`, `max_calls=250`, `load_avg=0.85`, `idle_cpu=35`, `fail_rate=0.5`
```
call_score = clamp(100 - (42/250)*100, 0, 100) = 83.2
load_score = clamp(100 - 0.85*50, 0, 100) = 57.5
idle_score = clamp(35, 0, 100) = 35.0
fail_score = clamp(100 - 0.5, 0, 100) = 99.5
score = 83.2×0.40 + 57.5×0.30 + 35.0×0.20 + 99.5×0.10 = 70.1
```
## Caching
`best_node_id`, `best_score`, and `fallback_active` are recalculated on every metric update.
`/api/route` reads them under RLock — O(1) constant time.
Выбор ноды из кэша зависит от [режима балансировки](routing.md#balancing-modes).
## Configuration
```json
{
"stale_threshold_sec": 20,
"scoring": {
"idle_cpu_min": 5,
"call_failure_rate_lethal": 15.0,
"weights": {
"call_score": 0.40,
"load_score": 0.30,
"idle_score": 0.20,
"fail_score": 0.10
}
}
}
```
Weights must sum to 1.0. All thresholds configurable in `config.json`.