/* * 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"` }