240 lines
8.5 KiB
Go
240 lines
8.5 KiB
Go
/*
|
||
* Copyright 2026 Safronov Grigorii
|
||
*
|
||
* Licensed under the CDDL, Version 1.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
*
|
||
* You may obtain a copy of the License at
|
||
* https://opensource.org/licenses/CDDL-1.0
|
||
*/
|
||
|
||
// Файл: internal/cluster/types.go
|
||
// Назначение: Общие типы данных для кластерных операций с поддержкой временных меток
|
||
// NOTE: NodeInfo, NodeRequest, ShardInfo, ClusterStatus определены в node.go и raft_coordinator.go
|
||
// Чтобы избежать дублирования, здесь определяем только вспомогательные типы и функции
|
||
|
||
package cluster
|
||
|
||
import (
|
||
"fmt"
|
||
"time"
|
||
)
|
||
|
||
|
||
|
||
// ========== ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ДЛЯ NodeInfo ==========
|
||
|
||
// NodeJoinedAt возвращает человекочитаемое время присоединения узла
|
||
func NodeJoinedAt(joinedAt int64) string {
|
||
if joinedAt == 0 {
|
||
return "not joined"
|
||
}
|
||
return time.UnixMilli(joinedAt).Format("2006-01-02 15:04:05.000")
|
||
}
|
||
|
||
// LastSeenAt возвращает человекочитаемое время последнего контакта
|
||
func LastSeenAt(lastSeen int64) string {
|
||
if lastSeen == 0 {
|
||
return "never"
|
||
}
|
||
return time.UnixMilli(lastSeen).Format("2006-01-02 15:04:05.000")
|
||
}
|
||
|
||
// GetNodeUptime возвращает время жизни узла в кластере
|
||
func GetNodeUptime(joinedAt int64) time.Duration {
|
||
if joinedAt == 0 {
|
||
return 0
|
||
}
|
||
return time.Duration(time.Now().UnixMilli()-joinedAt) * time.Millisecond
|
||
}
|
||
|
||
// IsNodeHealthy проверяет, здоров ли узел
|
||
func IsNodeHealthy(status string, lastSeen int64) bool {
|
||
return status == "active" && time.Now().UnixMilli()-lastSeen < 30000
|
||
}
|
||
|
||
// GetNodeAddress возвращает адрес узла
|
||
func GetNodeAddress(ip string, port int) string {
|
||
return fmt.Sprintf("%s:%d", ip, port)
|
||
}
|
||
|
||
// ========== ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ДЛЯ ShardInfo ==========
|
||
|
||
// GetShardUptime возвращает время жизни шарда
|
||
func GetShardUptime(createdAt int64) time.Duration {
|
||
if createdAt == 0 {
|
||
return 0
|
||
}
|
||
return time.Duration(time.Now().UnixMilli()-createdAt) * time.Millisecond
|
||
}
|
||
|
||
// IsShardHealthy проверяет, здоров ли шард
|
||
func IsShardHealthy(status string) bool {
|
||
return status == "active"
|
||
}
|
||
|
||
// GetShardLastRebalancedStr возвращает человекочитаемое время последней ребалансировки
|
||
func GetShardLastRebalancedStr(lastRebalanced int64) string {
|
||
if lastRebalanced == 0 {
|
||
return "never"
|
||
}
|
||
return time.UnixMilli(lastRebalanced).Format("2006-01-02 15:04:05.000")
|
||
}
|
||
|
||
// GetShardCreatedAtStr возвращает человекочитаемое время создания
|
||
func GetShardCreatedAtStr(createdAt int64) string {
|
||
if createdAt == 0 {
|
||
return "unknown"
|
||
}
|
||
return time.UnixMilli(createdAt).Format("2006-01-02 15:04:05.000")
|
||
}
|
||
|
||
// GetShardUpdatedAtStr возвращает человекочитаемое время обновления
|
||
func GetShardUpdatedAtStr(updatedAt int64) string {
|
||
if updatedAt == 0 {
|
||
return "unknown"
|
||
}
|
||
return time.UnixMilli(updatedAt).Format("2006-01-02 15:04:05.000")
|
||
}
|
||
|
||
// GetShardLeaderNode возвращает лидера шарда
|
||
func GetShardLeaderNode(leaderNode string) string {
|
||
return leaderNode
|
||
}
|
||
|
||
// GetShardNodeCount возвращает количество узлов в шарде
|
||
func GetShardNodeCount(nodes []string) int {
|
||
return len(nodes)
|
||
}
|
||
|
||
// GetShardReplicationFactor возвращает фактор репликации шарда
|
||
func GetShardReplicationFactor(nodes []string) int {
|
||
return len(nodes)
|
||
}
|
||
|
||
// ========== ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ДЛЯ ReplicationLogEntry ==========
|
||
|
||
// GetReplicationTimestampStr возвращает человекочитаемое время записи репликации
|
||
func GetReplicationTimestampStr(timestamp int64) string {
|
||
if timestamp == 0 {
|
||
return "unknown"
|
||
}
|
||
return time.UnixMilli(timestamp).Format("2006-01-02 15:04:05.000")
|
||
}
|
||
|
||
// IsReplicationSuccess проверяет, успешна ли операция репликации
|
||
func IsReplicationSuccess(status string) bool {
|
||
return status == "success"
|
||
}
|
||
|
||
// GetReplicationDuration возвращает длительность операции
|
||
func GetReplicationDuration(durationMs int64) time.Duration {
|
||
return time.Duration(durationMs) * time.Millisecond
|
||
}
|
||
|
||
// ========== ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ДЛЯ ClusterHealth ==========
|
||
|
||
// IsClusterHealthy проверяет, здоров ли кластер в целом
|
||
func IsClusterHealthy(overallScore float64) bool {
|
||
return overallScore >= 80
|
||
}
|
||
|
||
// IsClusterDegraded проверяет, деградирован ли кластер
|
||
func IsClusterDegraded(overallScore float64) bool {
|
||
return overallScore >= 50 && overallScore < 80
|
||
}
|
||
|
||
// IsClusterCritical проверяет, находится ли кластер в критическом состоянии
|
||
func IsClusterCritical(overallScore float64) bool {
|
||
return overallScore < 50
|
||
}
|
||
|
||
// GetHealthyNodesCount возвращает количество здоровых узлов
|
||
func GetHealthyNodesCount(nodes map[string]*NodeHealth) int {
|
||
if nodes == nil {
|
||
return 0
|
||
}
|
||
count := 0
|
||
for _, node := range nodes {
|
||
if node.Status == "active" {
|
||
count++
|
||
}
|
||
}
|
||
return count
|
||
}
|
||
|
||
// ========== ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ==========
|
||
|
||
// GetTimestamp возвращает текущий timestamp в миллисекундах
|
||
func GetTimestamp() int64 {
|
||
return time.Now().UnixMilli()
|
||
}
|
||
|
||
// FormatTimestamp форматирует timestamp в человекочитаемый вид
|
||
func FormatTimestamp(ts int64) string {
|
||
if ts == 0 {
|
||
return "never"
|
||
}
|
||
return time.UnixMilli(ts).Format("2006-01-02 15:04:05.000")
|
||
}
|
||
|
||
// IsTimestampExpired проверяет, истёк ли timestamp
|
||
func IsTimestampExpired(ts int64, ttl time.Duration) bool {
|
||
if ts == 0 {
|
||
return true
|
||
}
|
||
return time.Now().UnixMilli()-ts > ttl.Milliseconds()
|
||
}
|
||
|
||
// ========== ТИПЫ, КОТОРЫЕ НЕ ДУБЛИРУЮТСЯ В ДРУГИХ ФАЙЛАХ ==========
|
||
|
||
// NodeHealth представляет здоровье отдельного узла
|
||
type NodeHealth struct {
|
||
Status string `json:"status"`
|
||
LatencyMs int64 `json:"latency_ms"`
|
||
LastCheck int64 `json:"last_check"`
|
||
LastSuccess int64 `json:"last_success"`
|
||
LastFailure int64 `json:"last_failure"`
|
||
FailureCount int `json:"failure_count"`
|
||
}
|
||
|
||
// ClusterHealth представляет информацию о здоровье кластера
|
||
type ClusterHealth struct {
|
||
Nodes map[string]*NodeHealth `json:"nodes"`
|
||
OverallScore float64 `json:"overall_score"`
|
||
Recommendations string `json:"recommendations"`
|
||
CheckedAt int64 `json:"checked_at"`
|
||
}
|
||
|
||
// ConnectionInfo содержит информацию о соединении с узлом
|
||
type ConnectionInfo struct {
|
||
NodeID string `json:"node_id"`
|
||
Address string `json:"address"`
|
||
IsHealthy bool `json:"is_healthy"`
|
||
LastUsed int64 `json:"last_used"`
|
||
Failures uint32 `json:"failures"`
|
||
ConnectedAt int64 `json:"connected_at"`
|
||
}
|
||
|
||
// ClusterOperation представляет операцию в кластере
|
||
type ClusterOperation struct {
|
||
ID string `json:"id"`
|
||
Type string `json:"type"`
|
||
Status string `json:"status"`
|
||
CreatedAt int64 `json:"created_at"`
|
||
StartedAt int64 `json:"started_at"`
|
||
CompletedAt int64 `json:"completed_at"`
|
||
Details map[string]interface{} `json:"details"`
|
||
Error string `json:"error,omitempty"`
|
||
}
|
||
|
||
// WorkerPoolStats содержит статистику пула воркеров
|
||
type WorkerPoolStats struct {
|
||
MaxWorkers int `json:"max_workers"`
|
||
ActiveTasks int32 `json:"active_tasks"`
|
||
TotalTasks uint64 `json:"total_tasks"`
|
||
FailedTasks uint64 `json:"failed_tasks"`
|
||
QueueSize int `json:"queue_size"`
|
||
QueueCapacity int `json:"queue_capacity"`
|
||
}
|