Repository: envoyproxy/envoy
File: source/extensions/load_balancing_policies/common/thread_aware_lb_impl.cc (C++)

Code before:
  }

  const std::string value = remote_address->asString() + local_address->asString();
  std::string cookie_value = Hex::uint64ToHex(HashUtil::xxHash64(value));

  std::string cookie_header_value =
      Http::Utility::makeSetCookieValue(name, cookie_value, path, ttl, true, attributes);
  context->setHeadersModifier(
      [h = std::move(cookie_header_value)](Http::ResponseHeaderMap& headers) {
        headers.addReferenceKey(Http::Headers::get().SetCookie, h);
      });

  return cookie_value;
}

} // namespace

absl::Status ThreadAwareLoadBalancerBase::initialize() {
  // TODO(mattklein123): In the future, once initialized and the initial LB is built, it would be
  // better to use a background thread for computing LB updates. This has the substantial benefit
  // that if the LB computation thread falls behind, host set updates can be trivially collapsed.
  // I will look into doing this in a follow up. Doing everything using a background thread heavily
  // complicated initialization as the load balancer would need its own initialized callback. I
  // think the synchronous/asynchronous split is probably the best option.
  member_update_cb_ =
      priority_set_.addMemberUpdateCb([this](const HostVector&, const HostVector&) { refresh(); });

  refresh();
  return absl::OkStatus();
}

void ThreadAwareLoadBalancerBase::refresh() {
  auto per_priority_state_vector = std::make_shared<std::vector<PerPriorityStatePtr>>(
      priority_set_.hostSetsPerPriority().size());
  auto healthy_per_priority_load =
      std::make_shared<HealthyLoad>(per_priority_load_.healthy_priority_load_);
  auto degraded_per_priority_load =
      std::make_shared<DegradedLoad>(per_priority_load_.degraded_priority_load_);

  for (const auto& host_set : priority_set_.hostSetsPerPriority()) {
    const uint32_t priority = host_set->priority();
    (*per_priority_state_vector)[priority] = std::make_unique<PerPriorityState>();
    const auto& per_priority_state = (*per_priority_state_vector)[priority];
    // Copy panic flag from LoadBalancerBase. It is calculated when there is a change
    // in hosts set or hosts' health.
    per_priority_state->global_panic_ = per_priority_panic_[priority];

    // Normalize host and locality weights such that the sum of all normalized weights is 1.
    NormalizedHostWeightVector normalized_host_weights;
    double min_normalized_weight = 1.0;
    double max_normalized_weight = 0.0;

Review comment (refactor):
`refresh()` reads `per_priority_load_` and `per_priority_panic_` from  LoadBalancerBase. So there are 2 callbacks that are in order, but it could break for future's refactor. Could we make this ordering-independent by pulling the dirty-priority processing into a protected idempotent helper, and calling it both from both?

Code after:
    return {};
  }

  const std::string value = remote_address->asString() + local_address->asString();
  std::string cookie_value = Hex::uint64ToHex(HashUtil::xxHash64(value));

  std::string cookie_header_value =
      Http::Utility::makeSetCookieValue(name, cookie_value, path, ttl, true, attributes);
  context->setHeadersModifier(
      [h = std::move(cookie_header_value)](Http::ResponseHeaderMap& headers) {
        headers.addReferenceKey(Http::Headers::get().SetCookie, h);
      });

  return cookie_value;
}

} // namespace

absl::Status ThreadAwareLoadBalancerBase::initialize() {
  // TODO(mattklein123): In the future, once initialized and the initial LB is built, it would be
  // better to use a background thread for computing LB updates. This has the substantial benefit
  // that if the LB computation thread falls behind, host set updates can be trivially collapsed.
  // I will look into doing this in a follow up. Doing everything using a background thread heavily
  // complicated initialization as the load balancer would need its own initialized callback. I
  // think the synchronous/asynchronous split is probably the best option.
  if (Runtime::runtimeFeatureEnabled(
          "envoy.reloadable_features.coalesce_lb_rebuilds_on_batch_update")) {
    member_update_cb_ =
        priority_set_.addMemberUpdateCb([this](const HostVector&, const HostVector&) {
          processDirtyPriorities();
          refresh();
        });
  } else {
    priority_update_cb_ = priority_set_.addPriorityUpdateCb(
        [this](uint32_t, const HostVector&, const HostVector&) { refresh(); });
  }

  refresh();
  return absl::OkStatus();
}

void ThreadAwareLoadBalancerBase::refresh() {
  auto per_priority_state_vector = std::make_shared<std::vector<PerPriorityStatePtr>>(
      priority_set_.hostSetsPerPriority().size());
  auto healthy_per_priority_load =
      std::make_shared<HealthyLoad>(per_priority_load_.healthy_priority_load_);
  auto degraded_per_priority_load =
      std::make_shared<DegradedLoad>(per_priority_load_.degraded_priority_load_);

  for (const auto& host_set : priority_set_.hostSetsPerPriority()) {
    const uint32_t priority = host_set->priority();