-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
gsvc_service.go
150 lines (136 loc) · 4.73 KB
/
gsvc_service.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
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gsvc
import (
"context"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/internal/intlog"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/text/gstr"
)
// LocalService provides a default implements for interface Service.
type LocalService struct {
Head string // Service custom head string in service key.
Deployment string // Service deployment name, eg: dev, qa, staging, prod, etc.
Namespace string // Service Namespace, to indicate different services in the same environment with the same Name.
Name string // Name for the service.
Version string // Service version, eg: v1.0.0, v2.1.1, etc.
Endpoints Endpoints // Service Endpoints, pattern: IP:port, eg: 192.168.1.2:8000.
Metadata Metadata // Custom data for this service, which can be set using JSON by environment or command-line.
}
// NewServiceWithName creates and returns a default implements for interface Service by service name.
func NewServiceWithName(name string) Service {
s := &LocalService{
Name: name,
Metadata: make(Metadata),
}
s.autoFillDefaultAttributes()
return s
}
// NewServiceWithKV creates and returns a default implements for interface Service by key-value pair string.
func NewServiceWithKV(key, value string) (Service, error) {
var (
err error
array = gstr.Split(gstr.Trim(key, DefaultSeparator), DefaultSeparator)
)
if len(array) < 6 {
err = gerror.NewCodef(gcode.CodeInvalidParameter, `invalid service key "%s"`, key)
return nil, err
}
s := &LocalService{
Head: array[0],
Deployment: array[1],
Namespace: array[2],
Name: array[3],
Version: array[4],
Endpoints: NewEndpoints(array[5]),
Metadata: make(Metadata),
}
s.autoFillDefaultAttributes()
if len(value) > 0 {
if err = gjson.Unmarshal([]byte(value), &s.Metadata); err != nil {
err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `invalid service value "%s"`, value)
return nil, err
}
}
return s, nil
}
// GetName returns the name of the service.
// The name is necessary for a service, and should be unique among services.
func (s *LocalService) GetName() string {
return s.Name
}
// GetVersion returns the version of the service.
// It is suggested using GNU version naming like: v1.0.0, v2.0.1, v2.1.0-rc.
// A service can have multiple versions deployed at once.
// If no version set in service, the default version of service is "latest".
func (s *LocalService) GetVersion() string {
return s.Version
}
// GetKey formats and returns a unique key string for service.
// The result key is commonly used for key-value registrar server.
func (s *LocalService) GetKey() string {
serviceNameUnique := s.GetPrefix()
serviceNameUnique += DefaultSeparator + s.Endpoints.String()
return serviceNameUnique
}
// GetValue formats and returns the value of the service.
// The result value is commonly used for key-value registrar server.
func (s *LocalService) GetValue() string {
b, err := gjson.Marshal(s.Metadata)
if err != nil {
intlog.Errorf(context.TODO(), `%+v`, err)
}
return string(b)
}
// GetPrefix formats and returns the key prefix string.
// The result prefix string is commonly used in key-value registrar server
// for service searching.
//
// Take etcd server for example, the prefix string is used like:
// `etcdctl get /services/prod/hello.svc --prefix`
func (s *LocalService) GetPrefix() string {
s.autoFillDefaultAttributes()
return DefaultSeparator + gstr.Join(
[]string{
s.Head,
s.Deployment,
s.Namespace,
s.Name,
s.Version,
},
DefaultSeparator,
)
}
// GetMetadata returns the Metadata map of service.
// The Metadata is key-value pair map specifying extra attributes of a service.
func (s *LocalService) GetMetadata() Metadata {
return s.Metadata
}
// GetEndpoints returns the Endpoints of service.
// The Endpoints contain multiple host/port information of service.
func (s *LocalService) GetEndpoints() Endpoints {
return s.Endpoints
}
func (s *LocalService) autoFillDefaultAttributes() {
if s.Head == "" {
s.Head = gcmd.GetOptWithEnv(EnvPrefix, DefaultHead).String()
}
if s.Deployment == "" {
s.Deployment = gcmd.GetOptWithEnv(EnvDeployment, DefaultDeployment).String()
}
if s.Namespace == "" {
s.Namespace = gcmd.GetOptWithEnv(EnvNamespace, DefaultNamespace).String()
}
if s.Version == "" {
s.Version = gcmd.GetOptWithEnv(EnvVersion, DefaultVersion).String()
}
if s.Name == "" {
s.Name = gcmd.GetOptWithEnv(EnvName).String()
}
}