Skip to content

Commit

Permalink
Implement Functional Options (#33)
Browse files Browse the repository at this point in the history
* Removed seters from interface

* Removed config for hystrix

* Moved http client to its package

* Moved hystrix client to its package

* Updated examples with func options

* Updated readme with func options

* Added docs to structs

* Added missing import

* Fixed typos

* Setting defaults to httpclient

* Setting defaults to hystrix client

* Setting defaults to hystrix client
  • Loading branch information
italolelis authored and rShetty committed Jul 16, 2018
1 parent 9837605 commit 2f4870e
Show file tree
Hide file tree
Showing 14 changed files with 693 additions and 550 deletions.
91 changes: 52 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ The below example will print the contents of the google home page:
```go
// Create a new HTTP client with a default timeout
timeout := 1000 * time.Millisecond
client := heimdall.NewHTTPClient(timeout)
client := httpclient.NewClient(httpclient.WithTimeout(timeout))

// Use the clients GET method to create and execute the request
res, err := client.Get("http://google.com", nil)
Expand All @@ -58,7 +58,7 @@ You can also use the `*http.Request` object with the `http.Do` interface :

```go
timeout := 1000 * time.Millisecond
client := heimdall.NewHTTPClient(timeout)
client := httpclient.NewClient(httpclient.WithTimeout(timeout))

// Create an http.Request instance
req, _ := http.NewRequest(http.MethodGet, "http://google.com", nil)
Expand All @@ -74,18 +74,17 @@ fmt.Println(string(body))

### Creating a hystrix-like circuit breaker

You can use the `NewHystrixHTTPClient` function to create a client wrapped in a hystrix-like circuit breaker:
You can use the `hystrix.NewClient` function to create a client wrapped in a hystrix-like circuit breaker:

```go
// Create a new hystrix config, and input the command name, along with other required options
hystrixConfig := heimdall.NewHystrixConfig("google_get_request", heimdall.HystrixCommandConfig{
ErrorPercentThreshold : 20,
MaxConcurrentRequests: 30,
Timeout: 1000,
// Create a new hystrix-wrapped HTTP client with the command name, along with other required options
client := hystrix.NewClient(
hystrix.WithTimeout(10 * time.Millisecond),
hystrix.WithCommandName("google_get_request"),
hystrix.WithHystrixTimeout(1000),
hystrix.WithMaxConcurrentRequests(30),
hystrix.WithErrorPercentThreshold(20),
})
timeout := 10 * time.Millisecond
// Create a new hystrix-wrapped HTTP client
client := heimdall.NewHystrixHTTPClient(timeout, hystrixConfig)

// The rest is the same as the previous example
```
Expand All @@ -94,7 +93,7 @@ In the above example, there are two timeout values used: one for the hystrix con

### Creating a hystrix-like circuit breaker with fallbacks

You can use the `NewHystrixHTTPClient` function to create a client wrapped in a hystrix-like circuit breaker by passing in your own custom fallbacks:
You can use the `hystrix.NewClient` function to create a client wrapped in a hystrix-like circuit breaker by passing in your own custom fallbacks:

The fallback function will trigger when your code returns an error, or whenever it is unable to complete based on a variety of [health checks](https://github.com/Netflix/Hystrix/wiki/How-it-Works).

Expand All @@ -118,18 +117,19 @@ fallbackFn := func(err error) error {
return err
}

hystrixConfig := heimdall.NewHystrixConfig("MyCommand", heimdall.HystrixCommandConfig{
Timeout: 1100,
MaxConcurrentRequests: 100,
ErrorPercentThreshold: 25,
SleepWindow: 10,
RequestVolumeThreshold: 10,
FallbackFunc: fallbackFn,
})

timeout := 10 * time.Millisecond

// Create a new hystrix-wrapped HTTP client with the fallbackFunc as fall-back function
client := heimdall.NewHystrixHTTPClient(timeout, hystrixConfig)
client := hystrix.NewClient(
hystrix.WithTimeout(timeout),
hystrix.WithCommandName("MyCommand"),
hystrix.WithHystrixTimeout(1100),
hystrix.WithMaxConcurrentRequests(100),
hystrix.WithErrorPercentThreshold(20),
hystrix.WithSleepWindow(10),
hystrixWithRequestVolumeThreshold(10),
hystrix.WithFallbackFunc(fallbackFn),
})

// The rest is the same as the previous example
```
Expand All @@ -149,10 +149,12 @@ backoff := heimdall.NewConstantBackoff(backoffInterval, maximumJitterInterval)
retrier := heimdall.NewRetrier(backoff)

timeout := 1000 * time.Millisecond
client := heimdall.NewHTTPClient(timeout)
// Set the retry mechanism for the client, and the number of times you would like to retry
client.SetRetrier(retrier)
client.SetRetryCount(4)
// Create a new client, sets the retry mechanism, and the number of times you would like to retry
client := httpclient.NewClient(
httpclient.WithTimeout(timeout),
httpclient.WithRetrier(retrier),
httpclient.WithRetryCount(4),
)

// The rest is the same as the first example
```
Expand All @@ -172,10 +174,12 @@ backoff := heimdall.NewExponentialBackoff(initalTimeout, maxTimeout, exponentFac
retrier := heimdall.NewRetrier(backoff)

timeout := 1000 * time.Millisecond
client := heimdall.NewHTTPClient(timeout)
// Set the retry mechanism for the client, and the number of times you would like to retry
client.SetRetrier(retrier)
client.SetRetryCount(4)
// Create a new client, sets the retry mechanism, and the number of times you would like to retry
client := httpclient.NewClient(
httpclient.WithTimeout(timeout),
httpclient.WithRetrier(retrier),
httpclient.WithRetryCount(4),
)

// The rest is the same as the first example
```
Expand Down Expand Up @@ -216,9 +220,12 @@ backoff := &linearBackoff{100}
retrier := heimdall.NewRetrier(backoff)

timeout := 1000 * time.Millisecond
client := heimdall.NewHTTPClient(timeout)
client.SetRetrier(retrier)
client.SetRetryCount(4)
// Create a new client, sets the retry mechanism, and the number of times you would like to retry
client := httpclient.NewClient(
httpclient.WithTimeout(timeout),
httpclient.WithRetrier(retrier),
httpclient.WithRetryCount(4),
)

// The rest is the same as the first example
```
Expand All @@ -233,9 +240,11 @@ linearRetrier := NewRetrierFunc(func(retry int) time.Duration {
})

timeout := 1000 * time.Millisecond
client := heimdall.NewHTTPClient(timeout)
client.SetRetrier(linearRetrier)
client.SetRetryCount(4)
client := httpclient.NewClient(
httpclient.WithTimeout(timeout),
httpclient.WithRetrier(linearRetrier),
httpclient.WithRetryCount(4),
)
```

### Custom HTTP clients
Expand All @@ -259,15 +268,19 @@ func (c *myHTTPClient) Do(request *http.Request) (*http.Response, error) {
}
```

And set this with `httpClient.SetCustomHTTPClient(&myHTTPClient{client: http.DefaultClient})`
And set this with `httpclient.NewClient(httpclient.WithHTTPClient(&myHTTPClient{client: http.DefaultClient}))`

Now, each sent request will have the `Authorization` header to use HTTP basic authentication with the provided username and password.

This can be done for the hystrix client as well

```
hystrixClient.SetCustomHTTPClient(&myHTTPClient{
client: http.Client{Timeout: 25 * time.Millisecond}})
client := httpclient.NewClient(
httpclient.WithHTTPClient(&myHTTPClient{
client: http.Client{Timeout: 25 * time.Millisecond}
}
)
)
// The rest is the same as the first example
```
Expand Down
4 changes: 0 additions & 4 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,4 @@ type Client interface {
Patch(url string, body io.Reader, headers http.Header) (*http.Response, error)
Delete(url string, headers http.Header) (*http.Response, error)
Do(req *http.Request) (*http.Response, error)

SetRetryCount(count int)
SetRetrier(retrier Retriable)
SetCustomHTTPClient(customHTTPClient Doer)
}
39 changes: 0 additions & 39 deletions config.go

This file was deleted.

32 changes: 0 additions & 32 deletions config_test.go

This file was deleted.

72 changes: 38 additions & 34 deletions examples/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"time"

"github.com/gojektech/heimdall"
"github.com/gojektech/heimdall/httpclient"
"github.com/gojektech/heimdall/hystrix"
"github.com/pkg/errors"
)

Expand All @@ -17,13 +19,14 @@ const (
func httpClientUsage() error {
timeout := 100 * time.Millisecond

httpClient := heimdall.NewHTTPClient(timeout)
httpClient := httpclient.NewClient(
httpclient.WithHTTPTimeout(timeout),
httpclient.WithRetryCount(2),
httpclient.WithRetrier(heimdall.NewRetrier(heimdall.NewConstantBackoff(10, 5))),
)
headers := http.Header{}
headers.Set("Content-Type", "application/json")

httpClient.SetRetryCount(2)
httpClient.SetRetrier(heimdall.NewRetrier(heimdall.NewConstantBackoff(10, 5)))

response, err := httpClient.Get(baseURL, headers)
if err != nil {
return errors.Wrap(err, "failed to make a request to server")
Expand All @@ -42,16 +45,15 @@ func httpClientUsage() error {

func hystrixClientUsage() error {
timeout := 100 * time.Millisecond

hystrixConfig := heimdall.NewHystrixConfig("MyCommand", heimdall.HystrixCommandConfig{
Timeout: 1100,
MaxConcurrentRequests: 100,
ErrorPercentThreshold: 25,
SleepWindow: 10,
RequestVolumeThreshold: 10,
})

hystrixClient := heimdall.NewHystrixHTTPClient(timeout, hystrixConfig)
hystrixClient := hystrix.NewClient(
hystrix.WithHTTPTimeout(timeout),
hystrix.WithCommandName("MyCommand"),
hystrix.WithHystrixTimeout(1100),
hystrix.WithMaxConcurrentRequests(100),
hystrix.WithErrorPercentThreshold(25),
hystrix.WithSleepWindow(10),
hystrix.WithRequestVolumeThreshold(10),
)
headers := http.Header{}
response, err := hystrixClient.Get(baseURL, headers)
if err != nil {
Expand Down Expand Up @@ -79,18 +81,19 @@ func (c *myHTTPClient) Do(request *http.Request) (*http.Response, error) {
}

func customHTTPClientUsage() error {
httpClient := heimdall.NewHTTPClient(0 * time.Millisecond)

// replace with custom HTTP client
httpClient.SetCustomHTTPClient(&myHTTPClient{
client: http.Client{Timeout: 25 * time.Millisecond}})
httpClient := httpclient.NewClient(
httpclient.WithHTTPTimeout(0*time.Millisecond),
httpclient.WithHTTPClient(&myHTTPClient{
// replace with custom HTTP client
client: http.Client{Timeout: 25 * time.Millisecond},
}),
httpclient.WithRetryCount(2),
httpclient.WithRetrier(heimdall.NewRetrier(heimdall.NewConstantBackoff(10, 5))),
)

headers := http.Header{}
headers.Set("Content-Type", "application/json")

httpClient.SetRetryCount(2)
httpClient.SetRetrier(heimdall.NewRetrier(heimdall.NewConstantBackoff(10, 5)))

response, err := httpClient.Get(baseURL, headers)
if err != nil {
return errors.Wrap(err, "failed to make a request to server")
Expand All @@ -110,18 +113,19 @@ func customHTTPClientUsage() error {
func customHystrixClientUsage() error {
timeout := 0 * time.Millisecond

hystrixConfig := heimdall.NewHystrixConfig("MyCommand", heimdall.HystrixCommandConfig{
Timeout: 1100,
MaxConcurrentRequests: 100,
ErrorPercentThreshold: 25,
SleepWindow: 10,
RequestVolumeThreshold: 10,
})

hystrixClient := heimdall.NewHystrixHTTPClient(timeout, hystrixConfig)

hystrixClient.SetCustomHTTPClient(&myHTTPClient{
client: http.Client{Timeout: 25 * time.Millisecond}})
hystrixClient := hystrix.NewClient(
hystrix.WithHTTPTimeout(timeout),
hystrix.WithCommandName("MyCommand"),
hystrix.WithHystrixTimeout(1100),
hystrix.WithMaxConcurrentRequests(100),
hystrix.WithErrorPercentThreshold(25),
hystrix.WithSleepWindow(10),
hystrix.WithRequestVolumeThreshold(10),
hystrix.WithHTTPClient(&myHTTPClient{
// replace with custom HTTP client
client: http.Client{Timeout: 25 * time.Millisecond},
}),
)

headers := http.Header{}
response, err := hystrixClient.Get(baseURL, headers)
Expand Down
Loading

0 comments on commit 2f4870e

Please sign in to comment.