package node import ( "fmt" "time" "github.com/harmony-one/harmony/internal/utils" ) // ActionType is the input for Service Manager to operate. type ActionType byte // Constants for Action Type. const ( Start ActionType = iota Stop ) // ServiceType is service type. type ServiceType byte // Constants for Type. const ( SupportSyncing ServiceType = iota SupportClient SupportExplorer Test Done ) func (t ServiceType) String() string { switch t { case SupportClient: return "SupportClient" case SupportSyncing: return "SyncingSupport" case SupportExplorer: return "SupportExplorer" case Test: return "Test" case Done: return "Done" default: return "Unknown" } } // Constants for timing. const ( // WaitForStatusUpdate is the delay time to update new status. Currently set 1 second for development. Should be 30 minutes for production. WaitForStatusUpdate = time.Second * 1 ) // Action is type of service action. type Action struct { action ActionType serviceType ServiceType params map[string]interface{} } // ServiceInterface is the collection of functions any service needs to implement. type ServiceInterface interface { Start() Stop() } // ServiceStore stores all services for service manager. type ServiceStore struct { services map[ServiceType]ServiceInterface } // Register new service to service store. func (ss *ServiceStore) Register(t ServiceType, service ServiceInterface) { if ss.services == nil { ss.services = make(map[ServiceType]ServiceInterface) } ss.services[t] = service } // Start node. func (node *Node) Start() { node.RegisterServices() node.actionChannel = node.StartServiceManager() } // RegisterService is used for testing. func (node *Node) RegisterService(t ServiceType, service ServiceInterface) { node.serviceStore.Register(t, service) } // RegisterServices registers all service for a node with its role. func (node *Node) RegisterServices() { node.serviceStore = &ServiceStore{services: make(map[ServiceType]ServiceInterface)} } // SendAction sends action to action channel which is observed by service manager. func (node *Node) SendAction(action *Action) { node.actionChannel <- action } // TakeAction is how service manager handles the action. func (node *Node) TakeAction(action *Action) { if node.serviceStore == nil { utils.GetLogInstance().Error("Service store is not initialized.") return } if service, ok := node.serviceStore.services[action.serviceType]; ok { switch action.action { case Start: fmt.Printf("Start %s\n", action.serviceType) service.Start() case Stop: fmt.Printf("Stop %s\n", action.serviceType) service.Stop() } } } // StartServiceManager starts service manager. func (node *Node) StartServiceManager() chan *Action { ch := make(chan *Action) go func() { for { select { case action := <-ch: node.TakeAction(action) if action.serviceType == Done { return } case <-time.After(WaitForStatusUpdate): utils.GetLogInstance().Info("Waiting for new action.") } } }() return ch }