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

Changed next_endpoint method from random to round robin #124

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

chamorin
Copy link
Contributor

@chamorin chamorin commented Apr 4, 2024

Comment on lines +26 to +41
fn next_endpoint(&self, already_used_endpoints: &[String]) -> String {
let mut endpoints = self.endpoints.clone();

// if all endpoints are already used, return random endpoint
if endpoints.len() == already_used_endpoints.len() {
return already_used_endpoints
[rand::thread_rng().gen_range(0..already_used_endpoints.len())]
.to_string();
}

// round robin endpoints that are not already used
let mut endpoint = endpoints.remove(0);
while already_used_endpoints.contains(&endpoint) {
endpoint = endpoints.remove(0);
}
endpoint
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usual algorithm for this is to have an atomic counter, always add 1 to it and you do a x % N to get the next endpoint.

Seems you are adding lot of complexity with the already_used_endpoints, is it really required?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok so it's kind of a different thing than round robin, it's more a random + blocked endpoints. I suggest you use a HashSet to hold your already used endpoints. You than "diff" the blocked set with the full set which gives you the unused set and do a random pick on the "free" set.

The overall code will read much better. It will also remove the need for cloning the endpoints initially since you will diff two sets in read-only to get a new one which you will use to pick an element.

Also, it's probably better to remove the random pick and move to a real round robin also. But it complicates a bit when doing that use next not visited.

Normally I would have suggested you initially to just to a real round robin without the "used" list first. Usually it's enough, a random on small list usually yields bad results on retry since you often go back on the same value often.

log::info!(
"retrying request in {} second(s), at attempt {}, attempts left {}",
log::warn!(
"{{ \"endpoint\": \"{}\", \"path\": \"{}\", \"status\": \"{}\", \"retry_in\": {}, \"attempts\": {}, \"attempts_left\": {} }}",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why emitting JSON format now? Is it for some log extraction?

continue;
}

// If all endpoints are used, wait then retry with random endpoint
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is misleading as if retry is 3 but your have 5 endpoints, then it will not have exhausted all tries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants