pulse-lets-go/docs/architecture.md
Maksim Totmin 12a51a5ebe 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

7.4 KiB

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