Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add a configurable error handler for environment updates. Return response codes on HTTP errors #140

Merged
merged 4 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Client struct {
ctxAnalytics context.Context
log Logger
offlineHandler OfflineHandler
errorHandler func(handler FlagsmithErrorHandler)
}

// NewClient creates instance of Client with given configuration.
Expand Down Expand Up @@ -267,10 +268,18 @@ func (c *Client) UpdateEnvironment(ctx context.Context) error {
Get(c.config.baseURL + "environment-document/")

if err != nil {
return &FlagsmithAPIError{msg: fmt.Sprintf("flagsmith: error performing request to Flagsmith API: %s", err)}
f := &FlagsmithAPIError{msg: fmt.Sprintf("flagsmith: error performing request to Flagsmith API: %s", err)}
if c.errorHandler != nil {
c.errorHandler(FlagsmithErrorHandler{err, resp.StatusCode(), resp.Status()})
}
return f
}
if resp.StatusCode() != 200 {
return &FlagsmithAPIError{msg: fmt.Sprintf("flagsmith: unexpected response from Flagsmith API: %s", resp.Status())}
f := &FlagsmithAPIError{msg: fmt.Sprintf("flagsmith: unexpected response from Flagsmith API: %s", resp.Status())}
if c.errorHandler != nil {
c.errorHandler(FlagsmithErrorHandler{err, resp.StatusCode(), resp.Status()})
}
return f
}
c.environment.Store(&env)
identitiesWithOverrides := make(map[string]identities.IdentityModel)
Expand Down
32 changes: 32 additions & 0 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -675,3 +675,35 @@ func TestOfflineHandlerIsUsedWhenRequestFails(t *testing.T) {
assert.Equal(t, fixtures.Feature1ID, allFlags[0].FeatureID)
assert.Equal(t, fixtures.Feature1Value, allFlags[0].Value)
}

func TestPollErrorHandlerIsUsedWhenPollFails(t *testing.T) {
// Given
ctx := context.Background()
var capturedError error
var statusCode int
var status string

server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(http.StatusInternalServerError)
}))
defer server.Close()

// When
client := flagsmith.NewClient(fixtures.EnvironmentAPIKey,
flagsmith.WithBaseURL(server.URL+"/api/v1/"),
flagsmith.WithEnvironmentRefreshInterval(time.Duration(2)*time.Second),
ajinkyasurya marked this conversation as resolved.
Show resolved Hide resolved
flagsmith.WithErrorHandler(func(handler flagsmith.FlagsmithErrorHandler) {
capturedError = handler.Err
statusCode = handler.ResponseStatusCode
status = handler.ResponseStatus
}),
)

// when
_ = client.UpdateEnvironment(ctx)

// Then
assert.Equal(t, capturedError, nil)
assert.Equal(t, statusCode, 500)
assert.Equal(t, status, "500 Internal Server Error")
}
6 changes: 6 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ type FlagsmithAPIError struct {
msg string
}

type FlagsmithErrorHandler struct {
ajinkyasurya marked this conversation as resolved.
Show resolved Hide resolved
Err error
ResponseStatusCode int
ResponseStatus string
}

func (e FlagsmithClientError) Error() string {
return e.msg
}
Expand Down
7 changes: 7 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,10 @@
c.config.offlineMode = true
}
}

// WithErrorHandler provides a way to handle errors that occur during update of an environment

Check failure on line 121 in options.go

View workflow job for this annotation

GitHub Actions / golangci-lint

Comment should end in a period (godot)
func WithErrorHandler(handler func(handler FlagsmithErrorHandler)) Option {
return func(c *Client) {
c.errorHandler = handler
}
}
Loading