-
Notifications
You must be signed in to change notification settings - Fork 2
/
manager.go
157 lines (137 loc) · 3.42 KB
/
manager.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package service
import (
"fmt"
"github.com/PositionExchange/posichain/internal/utils"
"github.com/pkg/errors"
"github.com/rs/zerolog"
)
// Type is service type.
type Type byte
// Constants for Type.
const (
UnknownService Type = iota
ClientSupport
SupportExplorer
Consensus
BlockProposal
NetworkInfo
Pprof
Prometheus
Synchronize
CrosslinkSending
)
func (t Type) String() string {
switch t {
case SupportExplorer:
return "SupportExplorer"
case ClientSupport:
return "ClientSupport"
case Consensus:
return "Consensus"
case BlockProposal:
return "BlockProposal"
case NetworkInfo:
return "NetworkInfo"
case Pprof:
return "Pprof"
case Prometheus:
return "Prometheus"
case Synchronize:
return "Synchronize"
case CrosslinkSending:
return "CrosslinkSending"
default:
return "Unknown"
}
}
// Service is the collection of functions any service needs to implement.
type Service interface {
Start() error
Stop() error
}
// Manager stores all services for service manager.
type Manager struct {
services []Service
serviceMap map[Type]Service
logger zerolog.Logger
}
// NewManager creates a new manager
func NewManager() *Manager {
return &Manager{
services: nil,
serviceMap: make(map[Type]Service),
logger: *utils.Logger(),
}
}
// Register registers new service to service store.
func (m *Manager) Register(t Type, service Service) {
utils.Logger().Info().Int("service", int(t)).Msg("Register Service")
if _, ok := m.serviceMap[t]; ok {
utils.Logger().Error().Int("service", int(t)).Msg("This service is already included")
return
}
m.services = append(m.services, service)
m.serviceMap[t] = service
}
// GetServices returns all registered services.
func (m *Manager) GetServices() []Service {
return m.services
}
// GetService get the specified service
func (m *Manager) GetService(t Type) Service {
return m.serviceMap[t]
}
// StartServices run all registered services. If one of the starting service returns
// an error, closing all started services.
func (m *Manager) StartServices() (err error) {
started := make([]Service, 0, len(m.services))
defer func() {
if err != nil {
// If error is not nil, closing all services in reverse order
if stopErr := m.stopServices(started); stopErr != nil {
err = fmt.Errorf("%v; %v", err, stopErr)
}
}
}()
for _, service := range m.services {
t := m.typeByService(service)
m.logger.Info().Str("type", t.String()).Msg("Starting service")
if err = service.Start(); err != nil {
err = errors.Wrapf(err, "cannot start service [%v]", t.String())
return err
}
started = append(started, service)
}
return err
}
// StopServices stops all services in the reverse order.
func (m *Manager) StopServices() error {
return m.stopServices(m.services)
}
// stopServices stops given services in the reverse order.
func (m *Manager) stopServices(services []Service) error {
size := len(services)
var rErr error
for i := size - 1; i >= 0; i-- {
service := services[i]
t := m.typeByService(service)
m.logger.Info().Str("type", t.String()).Msg("Stopping service")
if err := service.Stop(); err != nil {
err = errors.Wrapf(err, "failed to stop service [%v]", t.String())
if rErr != nil {
rErr = fmt.Errorf("%v; %v", rErr, err)
} else {
rErr = err
}
}
}
return rErr
}
func (m *Manager) typeByService(target Service) Type {
for t, s := range m.serviceMap {
if s == target {
return t
}
}
return UnknownService
}