Repository: envoyproxy/envoy
File: source/extensions/bootstrap/reverse_tunnel/downstream_socket_interface/reverse_connection_io_handle.cc (C++)

Code before:
                        ReverseConnectionState::Recovered);
  ENVOY_LOG(debug,
            "reverse_tunnel: Marked host {} in cluster {} as Recovered with connection key {}",
            host_address, host_info.cluster_name, recovered_connection_key);
}

void ReverseConnectionIOHandle::updateConnectionState(const std::string& host_address,
                                                      const std::string& cluster_name,
                                                      const std::string& connection_key,
                                                      ReverseConnectionState new_state) {
  // Update connection state in host info and handle old state.
  auto host_it = host_to_conn_info_map_.find(host_address);
  if (host_it != host_to_conn_info_map_.end()) {
    // Remove old connection state if it exists.
    auto old_state_it = host_it->second.connection_states.find(connection_key);
    if (old_state_it != host_it->second.connection_states.end()) {
      ReverseConnectionState old_state = old_state_it->second;
      // Decrement old state gauge using unified function.
      updateStateGauge(host_address, cluster_name, old_state, false /* decrement */);
    }

    // Set new connection state.
    host_it->second.connection_states[connection_key] = new_state;
  }

  // Increment new state gauge using unified function.
  updateStateGauge(host_address, cluster_name, new_state, true /* increment */);

  ENVOY_LOG(debug,
            "ReverseConnectionIOHandle:Updated connection {} state to {} for host {} in cluster {}",
            connection_key, static_cast<int>(new_state), host_address, cluster_name);
}

void ReverseConnectionIOHandle::removeConnectionState(const std::string& host_address,
                                                      const std::string& cluster_name,
                                                      const std::string& connection_key) {
  // Remove connection state from host info and decrement gauge.
  auto host_it = host_to_conn_info_map_.find(host_address);
  if (host_it != host_to_conn_info_map_.end()) {
    auto state_it = host_it->second.connection_states.find(connection_key);
    if (state_it != host_it->second.connection_states.end()) {
      ReverseConnectionState old_state = state_it->second;
      // Decrement state gauge using unified function.
      updateStateGauge(host_address, cluster_name, old_state, false /* decrement */);
      // Remove gauge from map.
      host_it->second.connection_states.erase(state_it);
    }
  }

  ENVOY_LOG(debug, "reverse_tunnel: Removed connection {} state for host {} in cluster {}",
            connection_key, host_address, cluster_name);

Review comment (suggestion):
You'll need to decrement this counter in ReverseConnectionIOHandle::removeConnectionState() as well. Otherwise, when a downstream connection closes, connecting_count isn't decremented and maintainClusterConnections() will not re-initiate.

Code after:
  const std::string recovered_connection_key =
      host_address + "_" + host_info.cluster_name + "_backoff";
  updateConnectionState(host_address, host_info.cluster_name, recovered_connection_key,
                        ReverseConnectionState::Recovered);
  ENVOY_LOG(debug,
            "reverse_tunnel: Marked host {} in cluster {} as Recovered with connection key {}",
            host_address, host_info.cluster_name, recovered_connection_key);
}

void ReverseConnectionIOHandle::updateConnectionState(const std::string& host_address,
                                                      const std::string& cluster_name,
                                                      const std::string& connection_key,
                                                      ReverseConnectionState new_state) {
  // Update connection state in host info and handle old state.
  auto host_it = host_to_conn_info_map_.find(host_address);
  if (host_it != host_to_conn_info_map_.end()) {
    // Increment first and then decrement if needed.
    if (new_state == ReverseConnectionState::Connecting) {
      host_it->second.connecting_count++;
    }

    // Remove old connection state if it exists.
    auto old_state_it = host_it->second.connection_states.find(connection_key);
    if (old_state_it != host_it->second.connection_states.end()) {
      ReverseConnectionState old_state = old_state_it->second;
      if (old_state == ReverseConnectionState::Connecting) {
        host_it->second.connecting_count--;
      }
      // Decrement old state gauge using unified function.
      updateStateGauge(host_address, cluster_name, old_state, false /* decrement */);
    }

    // Set new connection state.
    host_it->second.connection_states[connection_key] = new_state;
  }

  // Increment new state gauge using unified function.
  updateStateGauge(host_address, cluster_name, new_state, true /* increment */);

  ENVOY_LOG(debug,
            "ReverseConnectionIOHandle:Updated connection {} state to {} for host {} in cluster {}",
            connection_key, static_cast<int>(new_state), host_address, cluster_name);
}

void ReverseConnectionIOHandle::removeConnectionState(const std::string& host_address,
                                                      const std::string& cluster_name,
                                                      const std::string& connection_key) {
  // Remove connection state from host info and decrement gauge.
  auto host_it = host_to_conn_info_map_.find(host_address);
  if (host_it != host_to_conn_info_map_.end()) {
    auto state_it = host_it->second.connection_states.find(connection_key);