mirror of
https://github.com/DeBrosOfficial/network.git
synced 2025-12-12 22:58:49 +00:00
- Updated Go version to 1.24.4 and adjusted toolchain. - Added indirect dependencies for `go-spew` and `go-difflib`. - Enhanced error handling in the `authMiddleware` to better distinguish between database errors and invalid API keys. - Implemented sticky port allocation for database instances, allowing reuse of previously saved ports across restarts. - Improved logging for port allocation and database recovery processes, ensuring better visibility and error tracking.
166 lines
4.7 KiB
Go
166 lines
4.7 KiB
Go
package rqlite
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// DatabaseStatus represents the state of a database cluster
|
|
type DatabaseStatus string
|
|
|
|
const (
|
|
StatusInitializing DatabaseStatus = "initializing"
|
|
StatusActive DatabaseStatus = "active"
|
|
StatusHibernating DatabaseStatus = "hibernating"
|
|
StatusWaking DatabaseStatus = "waking"
|
|
)
|
|
|
|
// PortPair represents HTTP and Raft ports for a database instance
|
|
type PortPair struct {
|
|
HTTPPort int `json:"http_port"`
|
|
RaftPort int `json:"raft_port"`
|
|
Host string `json:"host"`
|
|
}
|
|
|
|
// DatabaseMetadata contains metadata for a single database cluster
|
|
type DatabaseMetadata struct {
|
|
DatabaseName string `json:"database_name"` // e.g., "my_app_exampledb_1"
|
|
NodeIDs []string `json:"node_ids"` // Peer IDs hosting this database
|
|
PortMappings map[string]PortPair `json:"port_mappings"` // nodeID -> {HTTP port, Raft port}
|
|
Status DatabaseStatus `json:"status"` // Current status
|
|
CreatedAt time.Time `json:"created_at"`
|
|
LastAccessed time.Time `json:"last_accessed"`
|
|
LeaderNodeID string `json:"leader_node_id"` // Which node is rqlite leader
|
|
Version uint64 `json:"version"` // For conflict resolution
|
|
VectorClock map[string]uint64 `json:"vector_clock"` // For distributed consensus
|
|
}
|
|
|
|
// NodeCapacity represents capacity information for a node
|
|
type NodeCapacity struct {
|
|
NodeID string `json:"node_id"`
|
|
MaxDatabases int `json:"max_databases"` // Configured limit
|
|
CurrentDatabases int `json:"current_databases"` // How many currently active
|
|
PortRangeHTTP PortRange `json:"port_range_http"`
|
|
PortRangeRaft PortRange `json:"port_range_raft"`
|
|
LastHealthCheck time.Time `json:"last_health_check"`
|
|
IsHealthy bool `json:"is_healthy"`
|
|
}
|
|
|
|
// PortRange represents a range of available ports
|
|
type PortRange struct {
|
|
Start int `json:"start"`
|
|
End int `json:"end"`
|
|
}
|
|
|
|
// MetadataStore is an in-memory store for database metadata
|
|
type MetadataStore struct {
|
|
databases map[string]*DatabaseMetadata // key = database name
|
|
nodes map[string]*NodeCapacity // key = node ID
|
|
mu sync.RWMutex
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewMetadataStore creates a new metadata store
|
|
func NewMetadataStore() *MetadataStore {
|
|
return &MetadataStore{
|
|
databases: make(map[string]*DatabaseMetadata),
|
|
nodes: make(map[string]*NodeCapacity),
|
|
logger: zap.NewNop(), // Default no-op logger
|
|
}
|
|
}
|
|
|
|
// SetLogger sets the logger for the metadata store
|
|
func (ms *MetadataStore) SetLogger(logger *zap.Logger) {
|
|
ms.mu.Lock()
|
|
defer ms.mu.Unlock()
|
|
ms.logger = logger
|
|
}
|
|
|
|
// GetDatabase retrieves metadata for a database
|
|
func (ms *MetadataStore) GetDatabase(name string) *DatabaseMetadata {
|
|
ms.mu.RLock()
|
|
defer ms.mu.RUnlock()
|
|
if db, exists := ms.databases[name]; exists {
|
|
// Return a copy to prevent external modification
|
|
dbCopy := *db
|
|
return &dbCopy
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SetDatabase stores or updates metadata for a database
|
|
func (ms *MetadataStore) SetDatabase(db *DatabaseMetadata) {
|
|
ms.mu.Lock()
|
|
defer ms.mu.Unlock()
|
|
ms.databases[db.DatabaseName] = db
|
|
}
|
|
|
|
// DeleteDatabase removes metadata for a database
|
|
func (ms *MetadataStore) DeleteDatabase(name string) {
|
|
ms.mu.Lock()
|
|
defer ms.mu.Unlock()
|
|
delete(ms.databases, name)
|
|
}
|
|
|
|
// ListDatabases returns all database names
|
|
func (ms *MetadataStore) ListDatabases() []string {
|
|
ms.mu.RLock()
|
|
defer ms.mu.RUnlock()
|
|
names := make([]string, 0, len(ms.databases))
|
|
for name := range ms.databases {
|
|
names = append(names, name)
|
|
}
|
|
return names
|
|
}
|
|
|
|
// GetNode retrieves capacity info for a node
|
|
func (ms *MetadataStore) GetNode(nodeID string) *NodeCapacity {
|
|
ms.mu.RLock()
|
|
defer ms.mu.RUnlock()
|
|
if node, exists := ms.nodes[nodeID]; exists {
|
|
nodeCopy := *node
|
|
return &nodeCopy
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SetNode stores or updates capacity info for a node
|
|
func (ms *MetadataStore) SetNode(node *NodeCapacity) {
|
|
ms.mu.Lock()
|
|
defer ms.mu.Unlock()
|
|
ms.nodes[node.NodeID] = node
|
|
}
|
|
|
|
// DeleteNode removes capacity info for a node
|
|
func (ms *MetadataStore) DeleteNode(nodeID string) {
|
|
ms.mu.Lock()
|
|
defer ms.mu.Unlock()
|
|
delete(ms.nodes, nodeID)
|
|
}
|
|
|
|
// ListNodes returns all node IDs
|
|
func (ms *MetadataStore) ListNodes() []string {
|
|
ms.mu.RLock()
|
|
defer ms.mu.RUnlock()
|
|
ids := make([]string, 0, len(ms.nodes))
|
|
for id := range ms.nodes {
|
|
ids = append(ids, id)
|
|
}
|
|
return ids
|
|
}
|
|
|
|
// GetHealthyNodes returns IDs of healthy nodes
|
|
func (ms *MetadataStore) GetHealthyNodes() []string {
|
|
ms.mu.RLock()
|
|
defer ms.mu.RUnlock()
|
|
healthy := make([]string, 0)
|
|
for id, node := range ms.nodes {
|
|
if node.IsHealthy && node.CurrentDatabases < node.MaxDatabases {
|
|
healthy = append(healthy, id)
|
|
}
|
|
}
|
|
return healthy
|
|
}
|