-
Notifications
You must be signed in to change notification settings - Fork 146
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
make policy change handler try all fleet hosts before failing #1329
Merged
AndersonQ
merged 14 commits into
elastic:main
from
AndersonQ:1328-fix-update-fleet-hosts
Oct 20, 2022
Merged
Changes from 1 commit
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
d852a92
make policy change handler try all fleet hosts before failing
AndersonQ 7d26053
refactor remote client
AndersonQ 5885796
adjust tests
AndersonQ afd1c8e
adjust docs and tests
AndersonQ 13de63e
remove quick and dirty fix
AndersonQ e7fb0d0
fix typo
AndersonQ 5927b70
fix liting issues
AndersonQ e3521ef
pr review changes
AndersonQ 9caf99b
add changelog fragment
AndersonQ bc0e603
wee lint fixes
AndersonQ 3d47fe3
use hashicorp/go-multierror
AndersonQ 0aa99e0
don't double add the error
AndersonQ e9ee631
make the litner happy
AndersonQ f99490c
make the linter happy: the return
AndersonQ File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,8 @@ const ( | |
retryOnBadConnTimeout = 5 * time.Minute | ||
) | ||
|
||
var errRequestFailed = errors.New("request failed") | ||
|
||
type wrapperFunc func(rt http.RoundTripper) (http.RoundTripper, error) | ||
|
||
type requestClient struct { | ||
|
@@ -45,10 +47,10 @@ type requestClient struct { | |
// to the client. For authenticated calls or sending fields on every request, create a custom RoundTripper | ||
// implementation that will take care of the boilerplate. | ||
type Client struct { | ||
log *logger.Logger | ||
clientMu sync.Mutex | ||
clients []*requestClient | ||
config Config | ||
log *logger.Logger | ||
clientLock sync.Mutex | ||
clients []*requestClient | ||
config Config | ||
} | ||
|
||
// NewConfigFromURL returns a Config based on a received host. | ||
|
@@ -102,7 +104,7 @@ func NewWithConfig(log *logger.Logger, cfg Config, wrapper wrapperFunc) (*Client | |
hosts := cfg.GetHosts() | ||
hostCount := len(hosts) | ||
log.With("hosts", hosts).Debugf( | ||
"creating remote client with %d hosts", hostCount, hosts) | ||
"creating remote client with %d hosts", hostCount) | ||
clients := make([]*requestClient, hostCount) | ||
for i, host := range hosts { | ||
baseURL, err := urlutil.MakeURL(string(cfg.Protocol), p, host, 0) | ||
|
@@ -161,16 +163,15 @@ func (c *Client) Send( | |
} | ||
|
||
c.log.Debugf("Request method: %s, path: %s, reqID: %s", method, path, reqID) | ||
c.clientMu.Lock() | ||
defer c.clientMu.Unlock() | ||
c.clientLock.Lock() | ||
defer c.clientLock.Unlock() | ||
|
||
var err error | ||
var req *http.Request | ||
var resp *http.Response | ||
multiErr := errRequestFailed | ||
|
||
c.sortClients() | ||
for i, requester := range c.clients { | ||
req, err = requester.newRequest(method, path, params, body) | ||
req, err := requester.newRequest(method, path, params, body) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "fail to create HTTP request using method %s to %s", method, path) | ||
} | ||
|
@@ -201,9 +202,12 @@ func (c *Client) Send( | |
requester.lastErr = err | ||
requester.lastErrOcc = time.Now().UTC() | ||
|
||
// Using debug level as the error is only relevant if all clients fail. | ||
c.log.With("error", err).Debugf("requester %d/%d to host %s errored", | ||
msg := fmt.Sprintf("requester %d/%d to host %s errored", | ||
i, len(c.clients), requester.host) | ||
multiErr = fmt.Errorf("%s: %s: %s", msg, err, multiErr) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this feels hacky, i'd prefer https://github.com/hashicorp/go-multierror |
||
|
||
// Using debug level as the error is only relevant if all clients fail. | ||
c.log.With("error", err).Debugf(msg) | ||
continue | ||
} | ||
|
||
|
@@ -212,7 +216,7 @@ func (c *Client) Send( | |
return resp, nil | ||
} | ||
|
||
return nil, fmt.Errorf("all hosts failed, last error: %w", err) | ||
return nil, fmt.Errorf("all hosts failed: %w", multiErr) | ||
} | ||
|
||
// URI returns the remote URI. | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure we should shuffle arrays with each request, it adds unnecessary CPU cycles. maybe it would be better to shuffle on error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorting on each request will ensure we keep the previous behavior, preferring the no-error last used host to use next. Besides the number of fleet-server hosts are so small, that it's negligible the overhead to sort them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could possibly optimize skipping sorting if already known to be sorted before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it needs to be sorted every time because the sorting conditions change. Every time a host is used it loses priority, thus a new sorting is required.
It isn't much different from the original code that would do extensive search on each call to
Send
. Besides the host list is so small that i's negligible the impact on performance.