first commit

This commit is contained in:
Maksim Totmin
2026-06-25 14:27:41 +07:00
commit 44f5fa88e5
44 changed files with 8664 additions and 0 deletions
+217
View File
@@ -0,0 +1,217 @@
// Package models содержит общие типы данных pulse-lets-go.
package models
import "time"
// --- NATS: метрика от нижестоящей АТС ---
// NodeMetric — сообщение, публикуемое нодой в NATS каждые 5 сек.
type NodeMetric struct {
NodeID string `json:"node_id"`
TS int64 `json:"ts"` // unix timestamp
Status string `json:"status"` // "ok", "degraded", "down"
ActiveCalls int `json:"active_calls"`
MaxCalls int `json:"max_calls"`
IdleCPU float64 `json:"idle_cpu"` // 0..100 %
LoadAvg float64 `json:"load_avg"` // system load average (1m)
CallFailureRate float64 `json:"call_failure_rate"` // 0.0..100.0 %
}
// --- In-memory состояние ноды в engine ---
// NodeState — полное состояние ноды в памяти балансировщика.
// Содержит данные последней метрики + поля ручного управления.
type NodeState struct {
NodeMetric
Disabled bool `json:"disabled"`
DisabledReason string `json:"disabled_reason"`
Score float64 `json:"score"`
LethalReason string `json:"lethal_reason,omitempty"` // причина, если score = -100
}
// --- Trunk ---
// TrunkType — тип транка.
type TrunkType string
const (
TrunkIngress TrunkType = "ingress"
TrunkBalance TrunkType = "balance"
TrunkFallback TrunkType = "fallback"
)
// Trunk — модель транка (из trunks.json).
type Trunk struct {
ID string `json:"id"`
Name string `json:"name"`
Type TrunkType `json:"type"`
NodeID string `json:"node_id,omitempty"` // только для balance
Gateway string `json:"gateway"`
Codecs []string `json:"codecs,omitempty"`
Context string `json:"context,omitempty"`
Enabled bool `json:"enabled"`
Description string `json:"description,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// --- User ---
// UserRole — роль пользователя.
type UserRole string
const (
RoleAdmin UserRole = "admin"
RoleViewer UserRole = "viewer"
)
// User — модель пользователя (из users.json).
type User struct {
ID string `json:"id"`
Username string `json:"username"`
PasswordHash string `json:"password_hash"`
Role UserRole `json:"role"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// --- Auth ---
// LoginRequest — тело запроса на /api/auth/login.
type LoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
}
// LoginResponse — тело ответа /api/auth/login.
type LoginResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int64 `json:"expires_in"`
}
// --- /api/route ---
// RouteResponse — ответ на запрос маршрутизации.
type RouteResponse struct {
// Успех
NodeID string `json:"node_id,omitempty"`
Score float64 `json:"score,omitempty"`
SIPGateway string `json:"sip_gateway,omitempty"`
// Fallback
Fallback bool `json:"fallback,omitempty"`
Reason string `json:"reason,omitempty"`
// Общая информация о нодах
Nodes []RouteNodeInfo `json:"nodes,omitempty"`
// Ошибка
Error string `json:"error,omitempty"`
}
// RouteNodeInfo — информация о ноде в ответе маршрутизации.
type RouteNodeInfo struct {
ID string `json:"id"`
Score float64 `json:"score"`
Reason string `json:"reason,omitempty"`
Status string `json:"status"`
}
// --- API: Nodes ---
// ToggleNodeRequest — запрос на включение/выключение ноды.
type ToggleNodeRequest struct {
Disabled bool `json:"disabled"`
Reason string `json:"reason,omitempty"`
}
// NodeInfo — информация о ноде для фронта.
type NodeInfo struct {
NodeID string `json:"node_id"`
TS int64 `json:"ts"`
Status string `json:"status"`
ActiveCalls int `json:"active_calls"`
MaxCalls int `json:"max_calls"`
IdleCPU float64 `json:"idle_cpu"`
LoadAvg float64 `json:"load_avg"`
CallFailureRate float64 `json:"call_failure_rate"`
Disabled bool `json:"disabled"`
DisabledReason string `json:"disabled_reason,omitempty"`
Score float64 `json:"score"`
LethalReason string `json:"lethal_reason,omitempty"`
IsStale bool `json:"is_stale"`
SecondsAgo float64 `json:"seconds_ago"`
}
// --- API: Users ---
// CreateUserRequest — запрос на создание пользователя.
type CreateUserRequest struct {
Username string `json:"username"`
Password string `json:"password"`
Role UserRole `json:"role"`
}
// UpdateUserRequest — запрос на обновление пользователя.
type UpdateUserRequest struct {
Username *string `json:"username,omitempty"`
Password *string `json:"password,omitempty"`
Role *UserRole `json:"role,omitempty"`
}
// --- API: Trunks ---
// CreateTrunkRequest — запрос на создание транка.
type CreateTrunkRequest struct {
Name string `json:"name"`
Type TrunkType `json:"type"`
NodeID string `json:"node_id,omitempty"`
Gateway string `json:"gateway"`
Codecs []string `json:"codecs,omitempty"`
Context string `json:"context,omitempty"`
Enabled bool `json:"enabled"`
Description string `json:"description,omitempty"`
}
// UpdateTrunkRequest — запрос на обновление транка.
type UpdateTrunkRequest struct {
Name *string `json:"name,omitempty"`
Type *TrunkType `json:"type,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Gateway *string `json:"gateway,omitempty"`
Codecs []string `json:"codecs,omitempty"`
Context *string `json:"context,omitempty"`
Enabled *bool `json:"enabled,omitempty"`
Description *string `json:"description,omitempty"`
}
// --- Monitoring ---
// ZabbixNode — элемент LLD (Low-Level Discovery) для Zabbix.
type ZabbixNode struct {
NodeID string `json:"{#NODE_ID}"`
Status string `json:"{#STATUS}"`
ActiveCalls int `json:"{#ACTIVE_CALLS}"`
MaxCalls int `json:"{#MAX_CALLS}"`
IdleCPU float64 `json:"{#IDLE_CPU}"`
LoadAvg float64 `json:"{#LOAD_AVG}"`
CallFailureRate float64 `json:"{#CALL_FAILURE_RATE}"`
Score float64 `json:"{#SCORE}"`
Disabled bool `json:"{#DISABLED}"`
IsStale bool `json:"{#IS_STALE}"`
SecondsAgo float64 `json:"{#SECONDS_AGO}"`
}
// ZabbixResponse — ответ на запрос Zabbix LLD.
type ZabbixResponse struct {
Data []ZabbixNode `json:"data"`
}
// --- WebSocket ---
// WsMetricsMessage — сообщение, отправляемое по WebSocket.
type WsMetricsMessage struct {
Type string `json:"type"` // "nodes_update", "node_toggle", etc
Payload interface{} `json:"payload"`
}