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 Providers []config.NodeProviderConf 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 } adapters := d.Adapters if err := config.NormalizeAdapters(&adapters); err != nil { return nil, fmt.Errorf("node[%d] alias=%q: adapters: %w", i, d.Alias, err) } s.Add(&NodeRecord{ ID: nodeID, Alias: d.Alias, Token: d.Token, AgentKind: agentKind, Index: i, Adapters: adapters, Providers: d.Providers, Runtime: d.Runtime, }) } return s, nil }