iop/apps/edge/internal/node/store.go
toki 7008ff888f feat: edge node registry and service updates, roadmap sync
- Update edge node registry with snapshot tracking
- Fix mapper and store tests for registry changes
- Update transport server integration tests
- Add config support for new edge settings
- Sync roadmap with current phase progress
- Archive completed task groups
2026-06-03 17:53:44 +09:00

109 lines
2.4 KiB
Go

package node
import (
"fmt"
"sync"
"github.com/google/uuid"
"iop/packages/go/config"
)
// NodeRecord is the pre-registered node definition stored in edge.
type NodeRecord struct {
ID string
Alias string
Token string
AgentKind string
Index int
Adapters config.AdaptersConf
Runtime config.RuntimeConf
}
// NodeStore holds pre-registered node definitions, keyed by token.
type NodeStore struct {
mu sync.RWMutex
byToken map[string]*NodeRecord
byID map[string]*NodeRecord
}
func NewNodeStore() *NodeStore {
return &NodeStore{
byToken: make(map[string]*NodeRecord),
byID: make(map[string]*NodeRecord),
}
}
func (s *NodeStore) Add(rec *NodeRecord) {
s.mu.Lock()
defer s.mu.Unlock()
s.byToken[rec.Token] = rec
s.byID[rec.ID] = rec
}
func (s *NodeStore) FindByToken(token string) (*NodeRecord, bool) {
s.mu.RLock()
defer s.mu.RUnlock()
r, ok := s.byToken[token]
return r, ok
}
func (s *NodeStore) FindByID(id string) (*NodeRecord, bool) {
s.mu.RLock()
defer s.mu.RUnlock()
r, ok := s.byID[id]
return r, ok
}
func (s *NodeStore) All() []*NodeRecord {
s.mu.RLock()
defer s.mu.RUnlock()
out := make([]*NodeRecord, 0, len(s.byID))
for _, r := range s.byID {
out = append(out, r)
}
return out
}
// LoadFromConfig seeds the store from EdgeConfig.Nodes.
func LoadFromConfig(defs []config.NodeDefinition) (*NodeStore, error) {
s := NewNodeStore()
seenToken := make(map[string]bool)
seenAlias := make(map[string]bool)
seenID := make(map[string]bool)
for i, d := range defs {
if d.Token == "" {
return nil, fmt.Errorf("node[%d] alias=%q: token must not be empty", i, d.Alias)
}
if seenToken[d.Token] {
return nil, fmt.Errorf("node[%d] alias=%q: duplicate token", i, d.Alias)
}
if seenAlias[d.Alias] {
return nil, fmt.Errorf("node[%d] alias=%q: duplicate alias", i, d.Alias)
}
if d.ID != "" && seenID[d.ID] {
return nil, fmt.Errorf("node[%d] alias=%q: duplicate id %q", i, d.Alias, d.ID)
}
seenToken[d.Token] = true
seenAlias[d.Alias] = true
nodeID := d.ID
if nodeID == "" {
nodeID = uuid.NewString()
} else {
seenID[d.ID] = true
}
agentKind := d.AgentKind
if agentKind == "" {
agentKind = config.AgentKindGenericNode
}
s.Add(&NodeRecord{
ID: nodeID,
Alias: d.Alias,
Token: d.Token,
AgentKind: agentKind,
Index: i,
Adapters: d.Adapters,
Runtime: d.Runtime,
})
}
return s, nil
}