pulse-lets-go/docs/architecture.md
Maksim Totmin f20d5aa0e2 docs: restructure documentation into docs/ directory
- Create docs/ with 7 focused files: architecture, api, scoring, agent,
  deployment, freeswitch, development
- Rewrite README.md as concise overview with links to docs/
- Remove AGENTS.md (content merged into docs/ and README)
2026-06-25 22:35:19 +07:00

118 lines
7.4 KiB
Markdown

# Architecture
## Overview
pulse-lets-go — балансировщик телефонной нагрузки на базе FreeSWITCH + NATS.
Агенты PBX отправляют метрики в NATS каждые 5 секунд. Балансировщик вычисляет weighted score готовности каждой ноды, кэширует лучшую и отдаёт её FreeSWITCH через `/api/route` для следующего звонка.
## Data Flow
```
┌─────────────────────┐ ESL/AMI ┌──────────────────────┐
│ PBX-01 │──────────▶│ pulse-lets-go-agent │
│ (FS or Asterisk) │ collect │ (on each PBX node) │
├─────────────────────┤ ├──────────────────────┤
│ PBX-02 │──────────▶│ pulse-lets-go-agent │
│ (FS or Asterisk) │ ├──────────────────────┤
├─────────────────────┤ ├──────────────────────┤
│ PBX-N │──────────▶│ pulse-lets-go-agent │
│ (FS or Asterisk) │ └─────────┬────────────┘
└─────────────────────┘ │ pulse.metrics.<id>
│ every 5s
┌──────────────┐
│ NATS Server │
│ nats://:4222 │
└──────┬───────┘
┌──────────────────────┐
│ pulse-lets-go │
│ │
│ ┌────────────────┐ │
│ │ NATS Sub │ │
│ │ (pulse.metrics)│ │
│ └────────┬───────┘ │
│ ▼ │
│ ┌────────────────┐ │
│ │ Engine │ │
│ │ (scoring) │──│──▶ /api/route
│ └────────┬───────┘ │ ↓
│ ▼ │ FreeSWITCH bridge
│ ┌────────────────┐ │ sip:pbx-03:5060
│ │ REST API │──│──▶ /api/nodes
│ │ (JWT auth) │ │ /api/trunks
│ └────────┬───────┘ │ /api/users
│ ▼ │
│ ┌────────────────┐ │
│ │ WebSocket │──│──▶ SvelteKit UI
│ └────────────────┘ │ (ws://:8080/ws/metrics)
│ ┌────────────────┐ │
│ │ ESL Client │──│──▶ FreeSWITCH ESL
│ │ (gateways) │ │ :8021
│ └────────────────┘ │
│ ┌────────────────┐ │
│ │ Monitoring │──│──▶ /api/monitoring/prometheus
│ │ (API-key) │ │ /api/monitoring/zabbix
│ └────────────────┘ │
└──────────────────────┘
```
## Components
| Component | Role |
|-----------|------|
| **pulse-lets-go** | Central balancer: NATS subscriber, scoring engine, REST API, WebSocket hub, ESL client |
| **pulse-lets-go-agent** | Per-PBX metrics collector (FreeSWITCH ESL / Asterisk AMI) |
| **NATS** | Message bus — `pulse.metrics.<node_id>` subject |
| **FreeSWITCH** | Softswitch — uses `route.lua` + `mod_curl` to query `/api/route` |
| **SvelteKit UI** | Dashboard with real-time metrics via WebSocket |
## Tech Stack
| Component | Technology |
|-----------|-----------|
| Backend | Go 1.26, stdlib `net/http` + `http.ServeMux` |
| Frontend | SvelteKit 2 + Tailwind CSS 4 + Lucide |
| Auth | JWT (golang-jwt/v5, HS256) + bcrypt |
| Message bus | NATS (nats.go) |
| Storage | JSON files (`data/`) |
| ESL | Raw TCP (no external libraries) |
| Deployment | Single binary + systemd |
## Data Flow Summary
1. **Agent** collects metrics from PBX (ESL/AMI + /proc) every 5s
2. **Agent** publishes `pulse.metrics.<node_id>` to NATS
3. **Balancer** NATS subscriber receives metrics, updates in-memory node state
4. **Scoring engine** recalculates scores, caches best node
5. **FreeSWITCH** dialplan calls `/api/route` via `mod_curl`
6. **Balancer** returns best node's `sip_gateway` (O(1) from cache)
7. **FreeSWITCH** bridges the call to the returned gateway
## Project Structure
```
pulse-lets-go/
├── cmd/
│ ├── pulse-lets-go/ # Main entry point
│ ├── pulse-lets-go-agent/ # Metrics collector agent (FS / Asterisk)
│ ├── emulator/ # Metrics emulator for testing
│ └── siptest/ # SIP tester for e2e checks
├── internal/
│ ├── api/ # HTTP handlers (auth, nodes, trunks, users, monitoring, ws, route)
│ ├── config/ # JSON config manager (atomic save, thread-safe)
│ ├── engine/ # Scoring engine + router (sync.RWMutex, best-node cache)
│ ├── esl/ # FreeSWITCH ESL client (raw TCP)
│ ├── ami/ # Asterisk AMI client (raw TCP)
│ ├── log/ # ASCII metrics logger with rotation
│ ├── models/ # Data types (NodeMetric, NodeState, Trunk, User, ...)
│ └── nats/ # NATS subscriber
├── contrib/ # route.lua, agent configs
├── deploy/ # systemd unit
├── web/ # SvelteKit frontend
├── data/ # Runtime JSON files (gitignored)
└── docs/ # Documentation
```