-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathregistry.go
143 lines (120 loc) · 3.11 KB
/
registry.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
package service
import (
"context"
"github.com/Frontman-Labs/frontman/config"
"sync"
)
// ServiceRegistry holds the methods to interact with the backend service registry
type ServiceRegistry interface {
AddService(service *BackendService) error
UpdateService(service *BackendService) error
RemoveService(name string) error
GetServices() []*BackendService
GetTrie() *RoutingTrie
}
type baseRegistry struct {
mutex *sync.RWMutex
services []*BackendService
routingTrie *RoutingTrie
}
func NewServiceRegistry(ctx context.Context, serviceType string, config *config.Config) (ServiceRegistry, error) {
var (
reg ServiceRegistry
mu sync.RWMutex
err error
)
baseReg := baseRegistry{
mutex: &mu,
routingTrie: &RoutingTrie{
mutex: &mu,
},
}
switch serviceType {
case "redis":
redisClient, err := NewRedisClient(ctx, config.GlobalConfig.RedisURI)
if err != nil {
return nil, err
}
reg, err = NewRedisRegistry(ctx, redisClient, config.GlobalConfig.RedisNamespace, &baseReg)
if err != nil {
return nil, err
}
case "yaml":
reg, err = NewYAMLServiceRegistry(config.GlobalConfig.ServicesFile, &baseReg)
if err != nil {
return nil, err
}
case "mongo":
mongoClient, err := NewMongoClient(ctx, config.GlobalConfig.MongoURI)
if err != nil {
return nil, err
}
reg, err = NewMongoServiceRegistry(ctx, mongoClient, config.GlobalConfig.MongoDatabaseName, config.GlobalConfig.MongoCollectionName, &baseReg)
if err != nil {
return nil, err
}
case "memory": // For testing
reg = NewMemoryServiceRegistry(&baseReg)
default:
return nil, ErrUnsupportedServiceType{serviceType: serviceType}
}
// Initialise routing trie
baseReg.routingTrie.BuildRoutes(reg.GetServices())
return reg, nil
}
func (r *baseRegistry) getServices() []*BackendService {
services := make([]*BackendService, len(r.services))
copy(services, r.services)
return services
}
func (r *baseRegistry) addService(service *BackendService, apply func() error) error {
old := r.getServices()
for _, s := range r.services {
if s.Name == service.Name {
return ErrServiceExists{Name: service.Name}
}
}
r.services = append(r.services, service)
err := apply()
if err != nil {
r.services = old
return err
}
r.routingTrie.BuildRoutes(r.services)
return nil
}
func (r *baseRegistry) updateService(service *BackendService, apply func() error) error {
old := r.getServices()
for i, s := range r.services {
if s.Name == service.Name {
r.services[i] = service
err := apply()
if err != nil {
r.services = old
return err
}
r.routingTrie.BuildRoutes(r.services)
return nil
}
}
return ErrServiceNotFound{Name: service.Name}
}
func (r *baseRegistry) removeService(name string, apply func() error) error {
old := r.getServices()
for i, s := range r.services {
if s.Name == name {
r.services = append(r.services[:i], r.services[i+1:]...)
err := apply()
if err != nil {
r.services = old
return err
}
r.routingTrie.BuildRoutes(r.services)
return nil
}
}
return ErrServiceNotFound{Name: name}
}
func (r *baseRegistry) GetTrie() *RoutingTrie {
return r.routingTrie
}