Skip to content
This repository was archived by the owner on Dec 5, 2023. It is now read-only.

Commit 57f9c49

Browse files
author
Vishal Lal
committed
Add go-kit circuitbreaker
1 parent d3c94be commit 57f9c49

File tree

3 files changed

+199
-139
lines changed

3 files changed

+199
-139
lines changed

api/endpoints.go

Lines changed: 172 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ package api
66

77
import (
88
"github.com/go-kit/kit/endpoint"
9+
"github.com/go-kit/kit/circuitbreaker"
910
"github.com/go-kit/kit/tracing/opentracing"
1011
"github.com/microservices-demo/user/db"
1112
"github.com/microservices-demo/user/users"
1213
stdopentracing "github.com/opentracing/opentracing-go"
1314
"golang.org/x/net/context"
15+
"github.com/afex/hystrix-go/hystrix"
1416
)
1517

1618
// Endpoints collects the endpoints that comprise the Service.
@@ -46,176 +48,216 @@ func MakeEndpoints(s Service, tracer stdopentracing.Tracer) Endpoints {
4648

4749
// MakeLoginEndpoint returns an endpoint via the given service.
4850
func MakeLoginEndpoint(s Service) endpoint.Endpoint {
49-
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
50-
var span stdopentracing.Span
51-
span, ctx = stdopentracing.StartSpanFromContext(ctx, "login user")
52-
span.SetTag("service", "user")
53-
defer span.Finish()
54-
req := request.(loginRequest)
55-
u, err := s.Login(req.Username, req.Password)
56-
return userResponse{User: u}, err
57-
}
51+
hystrix.ConfigureCommand("Login", hystrix.CommandConfig{
52+
MaxConcurrentRequests: 100,
53+
})
54+
return circuitbreaker.Hystrix("Login")(
55+
func(ctx context.Context, request interface{}) (response interface{}, err error) {
56+
var span stdopentracing.Span
57+
span, ctx = stdopentracing.StartSpanFromContext(ctx, "login user")
58+
span.SetTag("service", "user")
59+
defer span.Finish()
60+
req := request.(loginRequest)
61+
u, err := s.Login(req.Username, req.Password)
62+
return userResponse{User: u}, err
63+
})
5864
}
5965

6066
// MakeRegisterEndpoint returns an endpoint via the given service.
6167
func MakeRegisterEndpoint(s Service) endpoint.Endpoint {
62-
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
63-
var span stdopentracing.Span
64-
span, ctx = stdopentracing.StartSpanFromContext(ctx, "register user")
65-
span.SetTag("service", "user")
66-
defer span.Finish()
67-
req := request.(registerRequest)
68-
id, err := s.Register(req.Username, req.Password, req.Email, req.FirstName, req.LastName)
69-
return postResponse{ID: id}, err
70-
}
68+
hystrix.ConfigureCommand("Register", hystrix.CommandConfig{
69+
MaxConcurrentRequests: 100,
70+
})
71+
return circuitbreaker.Hystrix("Register")(
72+
func(ctx context.Context, request interface{}) (response interface{}, err error) {
73+
var span stdopentracing.Span
74+
span, ctx = stdopentracing.StartSpanFromContext(ctx, "register user")
75+
span.SetTag("service", "user")
76+
defer span.Finish()
77+
req := request.(registerRequest)
78+
id, err := s.Register(req.Username, req.Password, req.Email, req.FirstName, req.LastName)
79+
return postResponse{ID: id}, err
80+
})
7181
}
7282

7383
// MakeUserGetEndpoint returns an endpoint via the given service.
7484
func MakeUserGetEndpoint(s Service) endpoint.Endpoint {
75-
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
76-
var span stdopentracing.Span
77-
span, ctx = stdopentracing.StartSpanFromContext(ctx, "get users")
78-
span.SetTag("service", "user")
79-
defer span.Finish()
85+
hystrix.ConfigureCommand("UserGet", hystrix.CommandConfig{
86+
MaxConcurrentRequests: 100,
87+
})
88+
return circuitbreaker.Hystrix("UserGet")(
89+
func(ctx context.Context, request interface{}) (response interface{}, err error) {
90+
var span stdopentracing.Span
91+
span, ctx = stdopentracing.StartSpanFromContext(ctx, "get users")
92+
span.SetTag("service", "user")
93+
defer span.Finish()
8094

81-
req := request.(GetRequest)
95+
req := request.(GetRequest)
8296

83-
userspan := stdopentracing.StartSpan("users from db", stdopentracing.ChildOf(span.Context()))
84-
usrs, err := s.GetUsers(req.ID)
85-
userspan.Finish()
86-
if req.ID == "" {
87-
return EmbedStruct{usersResponse{Users: usrs}}, err
88-
}
89-
if len(usrs) == 0 {
97+
userspan := stdopentracing.StartSpan("users from db", stdopentracing.ChildOf(span.Context()))
98+
usrs, err := s.GetUsers(req.ID)
99+
userspan.Finish()
100+
if req.ID == "" {
101+
return EmbedStruct{usersResponse{Users: usrs}}, err
102+
}
103+
if len(usrs) == 0 {
104+
if req.Attr == "addresses" {
105+
return EmbedStruct{addressesResponse{Addresses: make([]users.Address, 0)}}, err
106+
}
107+
if req.Attr == "cards" {
108+
return EmbedStruct{cardsResponse{Cards: make([]users.Card, 0)}}, err
109+
}
110+
return users.User{}, err
111+
}
112+
user := usrs[0]
113+
attrspan := stdopentracing.StartSpan("attributes from db", stdopentracing.ChildOf(span.Context()))
114+
db.GetUserAttributes(&user)
115+
attrspan.Finish()
90116
if req.Attr == "addresses" {
91-
return EmbedStruct{addressesResponse{Addresses: make([]users.Address, 0)}}, err
117+
return EmbedStruct{addressesResponse{Addresses: user.Addresses}}, err
92118
}
93119
if req.Attr == "cards" {
94-
return EmbedStruct{cardsResponse{Cards: make([]users.Card, 0)}}, err
120+
return EmbedStruct{cardsResponse{Cards: user.Cards}}, err
95121
}
96-
return users.User{}, err
97-
}
98-
user := usrs[0]
99-
attrspan := stdopentracing.StartSpan("attributes from db", stdopentracing.ChildOf(span.Context()))
100-
db.GetUserAttributes(&user)
101-
attrspan.Finish()
102-
if req.Attr == "addresses" {
103-
return EmbedStruct{addressesResponse{Addresses: user.Addresses}}, err
104-
}
105-
if req.Attr == "cards" {
106-
return EmbedStruct{cardsResponse{Cards: user.Cards}}, err
107-
}
108-
return user, err
109-
}
122+
return user, err
123+
})
110124
}
111125

112126
// MakeUserPostEndpoint returns an endpoint via the given service.
113127
func MakeUserPostEndpoint(s Service) endpoint.Endpoint {
114-
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
115-
var span stdopentracing.Span
116-
span, ctx = stdopentracing.StartSpanFromContext(ctx, "post user")
117-
span.SetTag("service", "user")
118-
defer span.Finish()
119-
req := request.(users.User)
120-
id, err := s.PostUser(req)
121-
return postResponse{ID: id}, err
122-
}
128+
hystrix.ConfigureCommand("UserPost", hystrix.CommandConfig{
129+
MaxConcurrentRequests: 100,
130+
})
131+
return circuitbreaker.Hystrix("UserPost")(
132+
func(ctx context.Context, request interface{}) (response interface{}, err error) {
133+
var span stdopentracing.Span
134+
span, ctx = stdopentracing.StartSpanFromContext(ctx, "post user")
135+
span.SetTag("service", "user")
136+
defer span.Finish()
137+
req := request.(users.User)
138+
id, err := s.PostUser(req)
139+
return postResponse{ID: id}, err
140+
})
123141
}
124142

125143
// MakeAddressGetEndpoint returns an endpoint via the given service.
126144
func MakeAddressGetEndpoint(s Service) endpoint.Endpoint {
127-
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
128-
var span stdopentracing.Span
129-
span, ctx = stdopentracing.StartSpanFromContext(ctx, "get users")
130-
span.SetTag("service", "user")
131-
defer span.Finish()
132-
req := request.(GetRequest)
133-
addrspan := stdopentracing.StartSpan("addresses from db", stdopentracing.ChildOf(span.Context()))
134-
adds, err := s.GetAddresses(req.ID)
135-
addrspan.Finish()
136-
if req.ID == "" {
137-
return EmbedStruct{addressesResponse{Addresses: adds}}, err
138-
}
139-
if len(adds) == 0 {
140-
return users.Address{}, err
141-
}
142-
return adds[0], err
143-
}
145+
hystrix.ConfigureCommand("AddressGet", hystrix.CommandConfig{
146+
MaxConcurrentRequests: 100,
147+
})
148+
return circuitbreaker.Hystrix("AddressGet")(
149+
func(ctx context.Context, request interface{}) (response interface{}, err error) {
150+
var span stdopentracing.Span
151+
span, ctx = stdopentracing.StartSpanFromContext(ctx, "get users")
152+
span.SetTag("service", "user")
153+
defer span.Finish()
154+
req := request.(GetRequest)
155+
addrspan := stdopentracing.StartSpan("addresses from db", stdopentracing.ChildOf(span.Context()))
156+
adds, err := s.GetAddresses(req.ID)
157+
addrspan.Finish()
158+
if req.ID == "" {
159+
return EmbedStruct{addressesResponse{Addresses: adds}}, err
160+
}
161+
if len(adds) == 0 {
162+
return users.Address{}, err
163+
}
164+
return adds[0], err
165+
})
144166
}
145167

146168
// MakeAddressPostEndpoint returns an endpoint via the given service.
147169
func MakeAddressPostEndpoint(s Service) endpoint.Endpoint {
148-
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
149-
var span stdopentracing.Span
150-
span, ctx = stdopentracing.StartSpanFromContext(ctx, "post address")
151-
span.SetTag("service", "user")
152-
defer span.Finish()
153-
req := request.(addressPostRequest)
154-
id, err := s.PostAddress(req.Address, req.UserID)
155-
return postResponse{ID: id}, err
156-
}
170+
hystrix.ConfigureCommand("AddressPost", hystrix.CommandConfig{
171+
MaxConcurrentRequests: 100,
172+
})
173+
return circuitbreaker.Hystrix("AddressPost")(
174+
func(ctx context.Context, request interface{}) (response interface{}, err error) {
175+
var span stdopentracing.Span
176+
span, ctx = stdopentracing.StartSpanFromContext(ctx, "post address")
177+
span.SetTag("service", "user")
178+
defer span.Finish()
179+
req := request.(addressPostRequest)
180+
id, err := s.PostAddress(req.Address, req.UserID)
181+
return postResponse{ID: id}, err
182+
})
157183
}
158184

159-
// MakeUserGetEndpoint returns an endpoint via the given service.
185+
// MakeCardGetEndpoint returns an endpoint via the given service.
160186
func MakeCardGetEndpoint(s Service) endpoint.Endpoint {
161-
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
162-
var span stdopentracing.Span
163-
span, ctx = stdopentracing.StartSpanFromContext(ctx, "get cards")
164-
span.SetTag("service", "user")
165-
defer span.Finish()
166-
req := request.(GetRequest)
167-
cardspan := stdopentracing.StartSpan("addresses from db", stdopentracing.ChildOf(span.Context()))
168-
cards, err := s.GetCards(req.ID)
169-
cardspan.Finish()
170-
if req.ID == "" {
171-
return EmbedStruct{cardsResponse{Cards: cards}}, err
172-
}
173-
if len(cards) == 0 {
174-
return users.Card{}, err
175-
}
176-
return cards[0], err
177-
}
187+
hystrix.ConfigureCommand("CardGet", hystrix.CommandConfig{
188+
MaxConcurrentRequests: 100,
189+
})
190+
return circuitbreaker.Hystrix("CardGet")(
191+
func(ctx context.Context, request interface{}) (response interface{}, err error) {
192+
var span stdopentracing.Span
193+
span, ctx = stdopentracing.StartSpanFromContext(ctx, "get cards")
194+
span.SetTag("service", "user")
195+
defer span.Finish()
196+
req := request.(GetRequest)
197+
cardspan := stdopentracing.StartSpan("addresses from db", stdopentracing.ChildOf(span.Context()))
198+
cards, err := s.GetCards(req.ID)
199+
cardspan.Finish()
200+
if req.ID == "" {
201+
return EmbedStruct{cardsResponse{Cards: cards}}, err
202+
}
203+
if len(cards) == 0 {
204+
return users.Card{}, err
205+
}
206+
return cards[0], err
207+
})
178208
}
179209

180210
// MakeCardPostEndpoint returns an endpoint via the given service.
181211
func MakeCardPostEndpoint(s Service) endpoint.Endpoint {
182-
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
183-
var span stdopentracing.Span
184-
span, ctx = stdopentracing.StartSpanFromContext(ctx, "post card")
185-
span.SetTag("service", "user")
186-
defer span.Finish()
187-
req := request.(cardPostRequest)
188-
id, err := s.PostCard(req.Card, req.UserID)
189-
return postResponse{ID: id}, err
190-
}
212+
hystrix.ConfigureCommand("CardPost", hystrix.CommandConfig{
213+
MaxConcurrentRequests: 100,
214+
})
215+
return circuitbreaker.Hystrix("CardPost")(
216+
func(ctx context.Context, request interface{}) (response interface{}, err error) {
217+
var span stdopentracing.Span
218+
span, ctx = stdopentracing.StartSpanFromContext(ctx, "post card")
219+
span.SetTag("service", "user")
220+
defer span.Finish()
221+
req := request.(cardPostRequest)
222+
id, err := s.PostCard(req.Card, req.UserID)
223+
return postResponse{ID: id}, err
224+
})
191225
}
192226

193-
// MakeLoginEndpoint returns an endpoint via the given service.
227+
// MakeDeleteEndpoint returns an endpoint via the given service.
194228
func MakeDeleteEndpoint(s Service) endpoint.Endpoint {
195-
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
196-
var span stdopentracing.Span
197-
span, ctx = stdopentracing.StartSpanFromContext(ctx, "delete entity")
198-
span.SetTag("service", "user")
199-
defer span.Finish()
200-
req := request.(deleteRequest)
201-
err = s.Delete(req.Entity, req.ID)
202-
if err == nil {
203-
return statusResponse{Status: true}, err
204-
}
205-
return statusResponse{Status: false}, err
206-
}
229+
hystrix.ConfigureCommand("Delete", hystrix.CommandConfig{
230+
MaxConcurrentRequests: 100,
231+
})
232+
return circuitbreaker.Hystrix("Delete")(
233+
func(ctx context.Context, request interface{}) (response interface{}, err error) {
234+
var span stdopentracing.Span
235+
span, ctx = stdopentracing.StartSpanFromContext(ctx, "delete entity")
236+
span.SetTag("service", "user")
237+
defer span.Finish()
238+
req := request.(deleteRequest)
239+
err = s.Delete(req.Entity, req.ID)
240+
if err == nil {
241+
return statusResponse{Status: true}, err
242+
}
243+
return statusResponse{Status: false}, err
244+
})
207245
}
208246

209247
// MakeHealthEndpoint returns current health of the given service.
210248
func MakeHealthEndpoint(s Service) endpoint.Endpoint {
211-
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
212-
var span stdopentracing.Span
213-
span, ctx = stdopentracing.StartSpanFromContext(ctx, "health check")
214-
span.SetTag("service", "user")
215-
defer span.Finish()
216-
health := s.Health()
217-
return healthResponse{Health: health}, nil
218-
}
249+
hystrix.ConfigureCommand("Health", hystrix.CommandConfig{
250+
MaxConcurrentRequests: 100,
251+
})
252+
return circuitbreaker.Hystrix("Health")(
253+
func(ctx context.Context, request interface{}) (response interface{}, err error) {
254+
var span stdopentracing.Span
255+
span, ctx = stdopentracing.StartSpanFromContext(ctx, "health check")
256+
span.SetTag("service", "user")
257+
defer span.Finish()
258+
health := s.Health()
259+
return healthResponse{Health: health}, nil
260+
})
219261
}
220262

221263
type GetRequest struct {

0 commit comments

Comments
 (0)