syntax = "proto3";

package gitaly;

import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";

option go_package = "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb";

// ServiceConfig defines the configuration that allows service owners to publish parameters to be
// automatically used by all clients of their service. gRPC doesn't export this protobuf. So, we
// built a minimized version to for Gitaly use. The completed version is defined at
// https://github.com/grpc/grpc-proto/blob/master/grpc/service_config/service_config.proto
message ServiceConfig {
  // protolint:disable:next REPEATED_FIELD_NAMES_PLURALIZED
  repeated LoadBalancingConfig load_balancing_config = 1;
  // protolint:disable:next REPEATED_FIELD_NAMES_PLURALIZED
  repeated MethodConfig method_config = 2;
}

// LoadBalancingConfig wraps around the round-robin strategies. Only one strategy can be selected.
message LoadBalancingConfig {
  oneof policy {
    // PickFirst strategy
    PickFirstConfig pick_first = 1 [json_name = "pick_first"];
    // RoundRobin strategy
    RoundRobinConfig round_robin = 2 [json_name = "round_robin"];
  }
}

// PickFirstConfig signals the pick_first load-balancing strategy. This strategy is the default
// strategy of grpc client libraries so that the connection has only one subchannel, which is the
// first address after resolution
message PickFirstConfig {
}

// RoundRobinConfig indicates the round_robin strategy. This strategy distributes the incoming
// requests to active subchannels in a round-robin fashion.
message RoundRobinConfig {
}

// Configuration for a method.
message MethodConfig {
  // Name is an object indicating which services/methods being affected by the config
  message Name {
    // service is name of the service,including its package. For example: gitaly.SmartHTTPService
    string service = 1;
    // method is the name of the method within the above service. Empty method name implies the
    // method policy is effective for all methods of the service
    string method = 2;
  }

  // RetryPolicy defines the configuration for exponential backoff when a request fails
  message RetryPolicy {
    // max_attempts is the total retry attempts client perform before bailing out
    uint32 max_attempts = 1;
    // initial_backoff is the minimum delay for the first retries
    google.protobuf.Duration initial_backoff = 2;
    // max_backoff is the minimum delay
    google.protobuf.Duration max_backoff = 3;
    // backoff_multiplier is the factor determining "how fast" the delay increases after each retry
    float backoff_multiplier = 4;
    // retryable_status_codes defines the list of eligible status codes. The status must be in
    // capitalized snake_case form. For example, UNAVAILABLE, FAILED_PRECONDITION
    repeated string retryable_status_codes = 5;
  }

  // name defines the list of affected services/methods
  // The name should be  is the definition of grpc. Nothing we can do about it
  // protolint:disable:next REPEATED_FIELD_NAMES_PLURALIZED
  repeated Name name = 1;
  // The following fields are unused by Gitaly at the moment. Please refer to the original
  // documentation for more information
  // protolint:disable FIELDS_HAVE_COMMENT
  google.protobuf.BoolValue wait_for_ready = 2;
  google.protobuf.Duration timeout = 3;
  google.protobuf.UInt32Value max_request_message_bytes = 4;
  google.protobuf.UInt32Value max_response_message_bytes = 5;
  // protolint:enable FIELDS_HAVE_COMMENT
  // retry_policy defines the exponential backoff configuration for the affected services/methods
  RetryPolicy retry_policy = 6;
}
