From d04a5644512ad620e14f23e5e984c5da36f75f26 Mon Sep 17 00:00:00 2001 From: agungdwiprasetyo Date: Mon, 5 Jun 2023 11:14:03 +0700 Subject: [PATCH] add hystrix circuit breaker move from core to this plugin --- circuit-breaker/go.mod | 15 +++ circuit-breaker/go.sum | 30 ++++++ circuit-breaker/hystrix_circuit_breaker.go | 102 +++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 circuit-breaker/go.mod create mode 100644 circuit-breaker/go.sum create mode 100644 circuit-breaker/hystrix_circuit_breaker.go diff --git a/circuit-breaker/go.mod b/circuit-breaker/go.mod new file mode 100644 index 0000000..9dd718c --- /dev/null +++ b/circuit-breaker/go.mod @@ -0,0 +1,15 @@ +module github.com/golangid/candi-plugin/circuitbreaker + +go 1.18 + +require github.com/gojektech/heimdall v5.0.2+incompatible + +require ( + github.com/afex/hystrix-go v0.0.0-20180209013831-27fae8d30f1a // indirect + github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect + github.com/jtolds/gls v4.2.1+incompatible // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect + github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c // indirect + github.com/stretchr/testify v1.8.2 // indirect +) diff --git a/circuit-breaker/go.sum b/circuit-breaker/go.sum new file mode 100644 index 0000000..5f5903a --- /dev/null +++ b/circuit-breaker/go.sum @@ -0,0 +1,30 @@ +github.com/afex/hystrix-go v0.0.0-20180209013831-27fae8d30f1a h1:kUr+IdWoKBJQ+e0LC/ysc1w5clvmxbvNNE+lK2yGPrQ= +github.com/afex/hystrix-go v0.0.0-20180209013831-27fae8d30f1a/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gojektech/heimdall v5.0.2+incompatible h1:mfGLnHNTKN7b1OMTO4ZvL3oT2P13kqTTV7owK7BZDck= +github.com/gojektech/heimdall v5.0.2+incompatible/go.mod h1:8hRIZ3+Kz0r3GAFI9QrUuvZht8ypg5Rs8schCXioLOo= +github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= +github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= +github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpkel/udgjbwB5Lktg9BtvJSh2DT0Hi6LPSyI2w= +github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/circuit-breaker/hystrix_circuit_breaker.go b/circuit-breaker/hystrix_circuit_breaker.go new file mode 100644 index 0000000..c8d346c --- /dev/null +++ b/circuit-breaker/hystrix_circuit_breaker.go @@ -0,0 +1,102 @@ +package circuitbreaker + +import ( + "crypto/tls" + "net/http" + "time" + + "github.com/gojektech/heimdall" + "github.com/gojektech/heimdall/hystrix" +) + +type ( + hystrixOption struct { + breakerName string + timeout time.Duration + retries int + sleepBetweenRetry time.Duration + tlsConfig *tls.Config + + additionalOption []hystrix.Option + } + + // HystrixOption func type + HystrixOption func(*hystrixOption) +) + +// HystrixSetRetries option func +func HystrixSetRetries(retries int) HystrixOption { + return func(h *hystrixOption) { + h.retries = retries + } +} + +// HystrixSetSleepBetweenRetry option func +func HystrixSetSleepBetweenRetry(sleepBetweenRetry time.Duration) HystrixOption { + return func(h *hystrixOption) { + h.sleepBetweenRetry = sleepBetweenRetry + } +} + +// HystrixSetTLS option func +func HystrixSetTLS(tlsConfig *tls.Config) HystrixOption { + return func(h *hystrixOption) { + h.tlsConfig = tlsConfig + } +} + +// HystrixSetTimeout option func +func HystrixSetTimeout(timeout time.Duration) HystrixOption { + return func(h *hystrixOption) { + h.timeout = timeout + } +} + +// HystrixSetBreakerName option func +func HystrixSetBreakerName(breakerName string) HystrixOption { + return func(h *hystrixOption) { + h.breakerName = breakerName + } +} + +// NewHystrixCircuitBreaker create new circuit breaker using hystrix +func NewHystrixCircuitBreaker(opts ...HystrixOption) interface { + Do(*http.Request) (*http.Response, error) +} { + clientOpt := new(hystrixOption) + + // set default value + clientOpt.retries = 5 + clientOpt.sleepBetweenRetry = 500 * time.Millisecond + clientOpt.timeout = 10 * time.Second + clientOpt.breakerName = "default" + for _, opt := range opts { + opt(clientOpt) + } + + // define a maximum jitter interval + maximumJitterInterval := 10 * time.Millisecond + // create a backoff + backoff := heimdall.NewConstantBackoff(clientOpt.sleepBetweenRetry, maximumJitterInterval) + // create a new retry mechanism with the backoff + retrier := heimdall.NewRetrier(backoff) + + hystrixClientOpt := []hystrix.Option{ + hystrix.WithHTTPTimeout(clientOpt.timeout), + hystrix.WithHystrixTimeout(clientOpt.timeout), + hystrix.WithRetrier(retrier), + hystrix.WithRetryCount(clientOpt.retries), + hystrix.WithCommandName(clientOpt.breakerName), + hystrix.WithFallbackFunc(func(err error) error { + return err + }), + } + hystrixClientOpt = append(hystrixClientOpt, clientOpt.additionalOption...) + if clientOpt.tlsConfig != nil { + hystrixClientOpt = append(hystrixClientOpt, hystrix.WithHTTPClient(&http.Client{ + Transport: &http.Transport{TLSClientConfig: clientOpt.tlsConfig}, + })) + } + + return hystrix.NewClient(hystrixClientOpt...) +}