Repository: envoyproxy/envoy
File: source/extensions/config_subscription/grpc/delta_subscription_state.h (C/C++)

Code before:
// list (thus contains version information), the resource becomes "complete". If the resource in the
// message is in "removed resources" list, it changes into the "waiting for server" state. If a
// server sends us a resource that we didn't request, it's going to be ignored.
//
// In the "wildcard subscription" scenario, "requested" category is the same as in "no wildcard
// subscription" scenario, with one exception - the unsubscribed "complete" resource is not removed
// from the cache, but it's moved to the "ambiguous" resources instead. At this point we are waiting
// for the server to tell us that this resource should be either moved to the "wildcard" resources,
// or dropped. Resources in "wildcard" category are only added there or dropped from there by the
// server. Resources from both "wildcard" and "ambiguous" categories can become "requested"
// "complete" resources if we subscribe to them again.
//
// The delta subscription state transitions between the two scenarios depending on whether we are
// subscribed to wildcard resource or not. Nothing special happens when we transition from "no
// wildcard subscription" to "wildcard subscription" scenario, but when transitioning in the other
// direction, we drop all the resources in "wildcard" and "ambiguous" categories.
class DeltaSubscriptionState : public Logger::Loggable<Logger::Id::config> {
public:
  DeltaSubscriptionState(std::string type_url, UntypedConfigUpdateCallbacks& watch_map,
                         Event::Dispatcher& dispatcher, XdsConfigTrackerOptRef xds_config_tracker);

  // Update which resources we're interested in subscribing to.
  void updateSubscriptionInterest(const absl::flat_hash_set<std::string>& cur_added,
                                  const absl::flat_hash_set<std::string>& cur_removed);
  void setMustSendDiscoveryRequest() { must_send_discovery_request_ = true; }
  void setDynamicContextChanged() {
    must_send_discovery_request_ = true;
    dynamic_context_changed_ = true;
  }
  bool dynamicContextChanged() const { return dynamic_context_changed_; }
  void clearDynamicContextChanged() { dynamic_context_changed_ = false; }

  // Whether there was a change in our subscription interest we have yet to inform the server of.
  bool subscriptionUpdatePending() const;

  // Marks the stream as fresh for the next reconnection attempt. If
  // should_send_initial_resource_versions is true, then the next request will
  // also populate the initial_resource_versions field in the first request (if
  // there are relevant resources).
  void markStreamFresh(bool should_send_initial_resource_versions);

  // May modify the order of resources to put all the non-heartbeat resources first.
  UpdateAck handleResponse(envoy::service::discovery::v3::DeltaDiscoveryResponse& message);

  void handleEstablishmentFailure();

  // Returns the next gRPC request proto to be sent off to the server, based on this object's
  // understanding of the current protocol state, and new resources that Envoy wants to request.
  envoy::service::discovery::v3::DeltaDiscoveryRequest getNextRequestAckless();

  // The WithAck version first calls the Ack-less version, then adds in the passed-in ack.

Review comment (refactor):
High-level question: why is there a need to know whether a dynamic context has been modified or not? Should the `must_send_discovery_request_` cover that?
(the way I understood this code was: the context change is on a higher level of abstraction than the gRPC-state. The gRPC-state is only interested in whether it needs to sent a discovery request or not). [in other words who is using `setMustSendDiscoveryRequest()` if not the dynamic context change]

Code after:
// message is in "removed resources" list, it changes into the "waiting for server" state. If a
// server sends us a resource that we didn't request, it's going to be ignored.
//
// In the "wildcard subscription" scenario, "requested" category is the same as in "no wildcard
// subscription" scenario, with one exception - the unsubscribed "complete" resource is not removed
// from the cache, but it's moved to the "ambiguous" resources instead. At this point we are waiting
// for the server to tell us that this resource should be either moved to the "wildcard" resources,
// or dropped. Resources in "wildcard" category are only added there or dropped from there by the
// server. Resources from both "wildcard" and "ambiguous" categories can become "requested"
// "complete" resources if we subscribe to them again.
//
// The delta subscription state transitions between the two scenarios depending on whether we are
// subscribed to wildcard resource or not. Nothing special happens when we transition from "no
// wildcard subscription" to "wildcard subscription" scenario, but when transitioning in the other
// direction, we drop all the resources in "wildcard" and "ambiguous" categories.
class DeltaSubscriptionState : public Logger::Loggable<Logger::Id::config> {
public:
  DeltaSubscriptionState(std::string type_url, UntypedConfigUpdateCallbacks& watch_map,
                         Event::Dispatcher& dispatcher, XdsConfigTrackerOptRef xds_config_tracker);

  // Update which resources we're interested in subscribing to.
  void updateSubscriptionInterest(const absl::flat_hash_set<std::string>& cur_added,
                                  const absl::flat_hash_set<std::string>& cur_removed);
  bool dynamicContextChanged() const { return dynamic_context_changed_; }
  void setDynamicContextChanged() { dynamic_context_changed_ = true; }
  void clearDynamicContextChanged() { dynamic_context_changed_ = false; }

  // Whether there was a change in our subscription interest we have yet to inform the server of.
  bool subscriptionUpdatePending() const;

  // Marks the stream as fresh for the next reconnection attempt. If
  // should_send_initial_resource_versions is true, then the next request will
  // also populate the initial_resource_versions field in the first request (if
  // there are relevant resources).
  void markStreamFresh(bool should_send_initial_resource_versions);

  // May modify the order of resources to put all the non-heartbeat resources first.
  UpdateAck handleResponse(envoy::service::discovery::v3::DeltaDiscoveryResponse& message);

  void handleEstablishmentFailure();

  // Returns the next gRPC request proto to be sent off to the server, based on this object's
  // understanding of the current protocol state, and new resources that Envoy wants to request.
  envoy::service::discovery::v3::DeltaDiscoveryRequest getNextRequestAckless();

  // The WithAck version first calls the Ack-less version, then adds in the passed-in ack.
  envoy::service::discovery::v3::DeltaDiscoveryRequest getNextRequestWithAck(const UpdateAck& ack);

  DeltaSubscriptionState(const DeltaSubscriptionState&) = delete;
  DeltaSubscriptionState& operator=(const DeltaSubscriptionState&) = delete;