Skip to content

Comments

adding round robin logic#20

Open
cjqzhao wants to merge 12 commits intodfawley:v0from
cjqzhao:roundrobiningitup
Open

adding round robin logic#20
cjqzhao wants to merge 12 commits intodfawley:v0from
cjqzhao:roundrobiningitup

Conversation

@cjqzhao
Copy link
Collaborator

@cjqzhao cjqzhao commented Jul 1, 2025

Add Round Robin logic and tests

@dfawley @easwars

Copy link
Collaborator

@easwars easwars left a comment

Choose a reason for hiding this comment

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

I havent looked at the tests yet.


impl LbPolicyBuilder for RoundRobinBuilder {
fn build(&self, options: LbPolicyOptions) -> Box<dyn LbPolicy> {
super::GLOBAL_LB_REGISTRY.add_builder(WrappedPickFirstBuilder {});
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: super::GLOBAL_LB_REGISTRY is used in two places. So, you might as well add a use statement for it. That way, the two places where it is used can simply be GLOBAL_LB_REGISTRY.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh, actually looks like you already have a use statement for it and you use it that way right below. So, please change all usages to be of that pattern.

Comment on lines 68 to 70
/**
Struct for round_robin.
*/
Copy link
Collaborator

Choose a reason for hiding this comment

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

Get rid of this comment. In general, use comments to talk about "why" something is being done instead of "what" is being done. In most cases, readers of the code will be able to figure out "what" is being done. But the "why" is the harder part. Of course, there are cases where comments that talk about the "what" are also useful (like where the code is a little obfuscated, or complicated and having a comment will make the reader's life easier).

Comment on lines 111 to 114
/// Register round robin as a LbPolicy.
pub fn reg() {
super::GLOBAL_LB_REGISTRY.add_builder(RoundRobinBuilder {});
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it would make sense to ensure that the call to add_builder happens only once even if this function is called multiple times. Using something like this might make sense: https://doc.rust-lang.org/std/sync/struct.Once.html

FYI: We need to do the same thing to the pick_first::reg function as well.

super::GLOBAL_LB_REGISTRY.add_builder(RoundRobinBuilder {});
}

struct WrapperPickFirstPolicy {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Naming nit. This one is named with a prefix of Wrapper while the builder is named with a prefix of Wrapped. Ideally, we should be consistent with the names.

fn build(&self, options: LbPolicyOptions) -> Box<dyn LbPolicy> {
pick_first::reg();
Box::new(WrapperPickFirstPolicy {
pick_first: GLOBAL_LB_REGISTRY.get_policy("pick_first").unwrap().build(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use pick_first::POLICY_NAME instead of the raw string pick_first.

Comment on lines 88 to 93
// Remove duplicates.
let mut uniques = HashSet::new();
addresses.retain(|e| uniques.insert(e.clone()));

// TODO(easwars): Implement address family interleaving as part of
// the dualstack implementation.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we need any of this here. Please correct me if I'm wrong.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes will delete!

Comment on lines 285 to 292
Err(error) => {
self.move_to_transient_failure(channel_controller);
if self.child_manager.has_updated() {
if let Some(pick_update) = self.child_manager.aggregate_states() {
channel_controller.update_picker(pick_update);
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't quite follow the logic here. This code as I read is moving the channel state to TF when it receives an error from the NR (irrespective of whether it had received a previous good update or not). And subsequently it sends a picker containing the aggregated states of the child policies. Can you please explain what is happening here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think I originally had Child Manager handling error from the resolver so I would call resolver_update on the child_manager here. I think it's best that Round Robin handles the logic directly instead so I changed it but I think I forgot to delete the last few lines of child manager aggregating state.

) {
self.child_manager
.subchannel_update(subchannel, state, channel_controller);
if self.child_manager.has_updated() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we need a better name for this has_updated method on the child manager.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Maybe child_has_updated or something

Comment on lines 313 to 315
// Build a new subchannel list with the most recent addresses received
// from the name resolver. This will start connecting from the first
// address in the list.
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 out of place. Please remove.

Comment on lines 326 to 330
if self.child_manager.has_updated() {
if let Some(pick_update) = self.child_manager.aggregate_states() {
channel_controller.update_picker(pick_update);
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This code block is repeated 5 times. Maybe you can make a method out of it, and replace all those 5 instances with a single line that calls the newly added method.

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