# Development ## Requirements - Go 1.26+ - Node.js 22+ - NATS Server (auto-downloaded via `make nats`) ## Build ```bash git clone git@git.totmin.ru:en2zmax/pulse-lets-go.git cd pulse-lets-go make build ``` ## Makefile Commands | Command | Description | |---------|-------------| | `make build` | Full build (Go + SvelteKit) | | `make dev` | Go backend + SvelteKit dev server (hot-reload) | | `make test` | Go tests with coverage | | `make test-race` | Tests with race detector | | `make lint` | `go vet ./...` | | `make fmt` | `go fmt ./...` | | `make build-agent` | Build pulse-lets-go-agent | | `make build-siptest` | Build SIP tester | | `make emulate-*` | Metrics emulation (normal, overload, chaos, stale, ...) | | `make siptest-*` | SIP testing (uas, uac, full) | | `make nats` | Start local NATS server | ## Running Locally ```bash # Terminal 1: NATS make nats # Terminal 2: balancer ./bin/pulse-lets-go # Terminal 3: metrics emulator (3 healthy nodes) make emulate-normal ``` ## Code Style Before committing: ```bash make fmt make lint make test ``` ## Project Structure ``` pulse-lets-go/ ├── cmd/ │ ├── pulse-lets-go/ # Main entry point │ ├── pulse-lets-go-agent/ # Metrics collector (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) ``` ## Adding a New Endpoint 1. Define model in `internal/models/types.go` 2. Implement handler in `internal/api/.go` 3. Register route in `internal/api/router.go` with required middleware (auth, admin) 4. Add tests in `internal/engine/engine_test.go` if scoring is affected ## Commit Messages [Conventional Commits](https://www.conventionalcommits.org/) format: ``` feat: add support for custom scoring weights fix: handle nil ESL client in route handler docs: add API reference table to README refactor: extract scoring logic into separate method test: add lethal condition tests for stale nodes chore: update Go dependencies ``` ## Implementation Order 1. `cmd/pulse-lets-go/main.go` + Go module + пустая структура `internal/` 2. `internal/models/` — все типы данных 3. `internal/config/` — чтение/запись JSON, атомарное сохранение 4. `internal/nats/` — подписка, in-memory store 5. `internal/engine/` — scorer + router 6. `internal/api/` — все хендлеры 7. `internal/log/` — ASCII-логгер + ring buffer 8. Web-фронт (SvelteKit) 9. Makefile + systemd unit 10. Тесты + graceful shutdown ## PR Process 1. Branch from `main`, named `feature/`, `fix/`, or `docs/` 2. One PR — one logical change 3. All tests pass (`make test`) 4. Code passes `make lint` 5. If API changes — update docs