Skip to content

Commit 5e75c30

Browse files
committed
fetch apolloConfig
1 parent f1d9f91 commit 5e75c30

File tree

12 files changed

+457
-31
lines changed

12 files changed

+457
-31
lines changed

apollo/client.go

Lines changed: 103 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,115 @@
11
package apollo
22

33
import (
4-
"crypto/tls"
5-
6-
"github.com/libgox/addr"
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"net/http"
78
)
89

910
type Client interface {
11+
GetStringValue(key string) string
1012
}
1113

12-
type Config struct {
13-
Address addr.Address
14-
// TlsConfig configuration information for tls.
15-
TlsConfig *tls.Config
14+
type innerClient struct {
15+
ctx context.Context
16+
config *Config
17+
storage *storage
18+
poller *longPoll
19+
listener Listener
1620
}
1721

1822
func NewClient(config *Config) (Client, error) {
19-
return newClient(config)
23+
if config.Logger != nil {
24+
SetLogger(config.Logger)
25+
}
26+
ctx := context.Background()
27+
c := &innerClient{
28+
ctx: ctx,
29+
config: config,
30+
storage: newStorage(config.Namespace),
31+
}
32+
c.poller = newLongPoll(config, c.updateHandle)
33+
34+
go c.poller.start(c.ctx)
35+
36+
return c, nil
37+
}
38+
39+
func (i *innerClient) updateHandle() error {
40+
change, err := i.sync()
41+
if err != nil {
42+
return err
43+
}
44+
if change == nil || len(change.Changes) == 0 {
45+
return fmt.Errorf("no changes to sync")
46+
}
47+
if i.listener != nil {
48+
i.listener.OnChange(change)
49+
}
50+
return nil
51+
}
52+
53+
func (i *innerClient) sync() (*ChangeEvent, error) {
54+
log.Infof("sync namespace %s with remote config server", i.config.Namespace)
55+
url := i.config.GetSyncURI()
56+
r := &requester{
57+
client: &http.Client{
58+
Transport: &http.Transport{
59+
TLSClientConfig: i.config.TLSConfig,
60+
},
61+
},
62+
retries: 3,
63+
}
64+
result, err := r.do(i.ctx, url, r.retries)
65+
if err != nil || len(result) == 0 {
66+
return nil, err
67+
}
68+
69+
ac := &apolloConfiguration{}
70+
if err = json.Unmarshal(result, ac); err != nil {
71+
return nil, err
72+
}
73+
return i.updateCache(ac)
74+
}
75+
76+
func (i *innerClient) updateCache(ac *apolloConfiguration) (*ChangeEvent, error) {
77+
var change = &ChangeEvent{
78+
Namespace: ac.Namespace,
79+
Changes: make(map[string]*Change),
80+
}
81+
c := i.storage.loadCache(ac.Namespace)
82+
83+
c.data.Range(func(k, v interface{}) bool {
84+
key := k.(string)
85+
value := v.(string)
86+
if _, ok := ac.Configurations[key]; !ok {
87+
c.data.Delete(key)
88+
}
89+
change.Changes[key] = onDelete(key, value)
90+
return true
91+
})
92+
93+
for k, v := range ac.Configurations {
94+
old, ok := c.data.Load(k)
95+
if !ok {
96+
change.Changes[k] = onAdd(k, v)
97+
c.data.Store(k, v)
98+
continue
99+
}
100+
if old.(string) != v {
101+
change.Changes[k] = onModify(k, old.(string), v)
102+
}
103+
c.data.Store(k, v)
104+
}
105+
// todo: save releaseKey?
106+
return change, nil
107+
}
108+
109+
func (i *innerClient) GetStringValue(key string) string {
110+
v, ok := i.storage.loadCache(i.config.Namespace).data.Load(key)
111+
if !ok {
112+
return ""
113+
}
114+
return v.(string)
20115
}

apollo/client_impl.go

Lines changed: 0 additions & 15 deletions
This file was deleted.

apollo/client_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package apollo
2+
3+
import "testing"
4+
5+
func TestNewClient(t *testing.T) {
6+
c, _ := NewClient(&Config{
7+
AppID: "appId",
8+
Cluster: "default",
9+
Namespace: "apollo",
10+
Address: "localhost:8080",
11+
Secret: "",
12+
TLSConfig: nil,
13+
Logger: nil,
14+
})
15+
value := c.GetStringValue("")
16+
t.Log(value)
17+
}

apollo/config.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package apollo
2+
3+
import (
4+
"crypto/tls"
5+
"fmt"
6+
"net/url"
7+
)
8+
9+
type Config struct {
10+
AppID string
11+
Cluster string
12+
Namespace string
13+
Address string
14+
Secret string
15+
// TlsConfig configuration information for tls.
16+
TLSConfig *tls.Config
17+
Logger Logger
18+
}
19+
20+
func (c *Config) GetNotifyURLSuffix(notifications string) string {
21+
return fmt.Sprintf("%s/notifications/v2?appId=%s&cluster=%s&notifications=%s",
22+
c.GetUrlPrefix(),
23+
url.QueryEscape(c.AppID),
24+
url.QueryEscape(c.Cluster),
25+
url.QueryEscape(notifications))
26+
}
27+
28+
func (c *Config) GetSyncURI() string {
29+
return fmt.Sprintf("%s/configs/%s/%s/%s?releaseKey=&ip=%s",
30+
c.GetUrlPrefix(),
31+
url.QueryEscape(c.AppID),
32+
url.QueryEscape(c.Cluster),
33+
url.QueryEscape(c.Namespace),
34+
GetLocalIP())
35+
}
36+
37+
func (c *Config) GetUrlPrefix() string {
38+
var urlPrefix string
39+
if c.TLSConfig != nil {
40+
urlPrefix = "https://"
41+
} else {
42+
urlPrefix = "http://"
43+
}
44+
return urlPrefix
45+
}

apollo/event.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package apollo
2+
3+
type ChangeType int
4+
5+
const (
6+
ADD ChangeType = iota
7+
8+
MODIFY
9+
10+
DELETE
11+
)
12+
13+
type Listener interface {
14+
OnChange(event *ChangeEvent)
15+
}
16+
17+
type Change struct {
18+
Key string
19+
OldValue string
20+
NewValue string
21+
ChangeType ChangeType
22+
}
23+
24+
type ChangeEvent struct {
25+
Namespace string
26+
NotificationID int
27+
Changes map[string]*Change
28+
}
29+
30+
func onDelete(key, value string) *Change {
31+
return &Change{
32+
Key: key,
33+
ChangeType: DELETE,
34+
OldValue: value,
35+
}
36+
}
37+
38+
func onModify(key, oldValue, newValue string) *Change {
39+
return &Change{
40+
Key: key,
41+
ChangeType: MODIFY,
42+
OldValue: oldValue,
43+
NewValue: newValue,
44+
}
45+
}
46+
47+
func onAdd(key, value string) *Change {
48+
return &Change{
49+
Key: key,
50+
ChangeType: ADD,
51+
NewValue: value,
52+
}
53+
}

apollo/logger.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package apollo
2+
3+
type Logger interface {
4+
Info(format string, args ...interface{})
5+
6+
Error(format string, args ...interface{})
7+
8+
Warning(format string, args ...interface{})
9+
10+
Infof(format string, args ...interface{})
11+
12+
Errorf(format string, args ...interface{})
13+
14+
Warningf(format string, args ...interface{})
15+
}
16+
17+
var log Logger = &defaultLogger{}
18+
19+
type defaultLogger struct {
20+
}
21+
22+
func SetLogger(logger Logger) {
23+
log = logger
24+
}
25+
26+
func (d defaultLogger) Info(format string, args ...interface{}) {
27+
}
28+
29+
func (d defaultLogger) Error(format string, args ...interface{}) {
30+
}
31+
32+
func (d defaultLogger) Warning(format string, args ...interface{}) {
33+
}
34+
35+
func (d defaultLogger) Infof(format string, args ...interface{}) {
36+
}
37+
38+
func (d defaultLogger) Errorf(format string, args ...interface{}) {
39+
}
40+
41+
func (d defaultLogger) Warningf(format string, args ...interface{}) {
42+
}

apollo/notification.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package apollo
2+
3+
import "encoding/json"
4+
5+
const defaultNotificationID int = -1
6+
7+
type notification struct {
8+
Namespace string `json:"namespace"`
9+
NotificationID int `json:"notificationId"`
10+
}
11+
12+
func (n *notification) String() string {
13+
res, err := json.Marshal([]*notification{n})
14+
if err != nil {
15+
return ""
16+
}
17+
return string(res)
18+
}

0 commit comments

Comments
 (0)