// Copyright 2018 the Istio Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

// $title: Redis Quota
// $overview: Adapter for a Redis-based quota management system.
// $location: https://istio.io/docs/reference/config/adapters/redisquota.html

// The `redisquota` adapter can be used to support Istio's quota management
// system. It depends on a Redis server to store quota values.
package adapter.redisquota.config;

import "google/protobuf/duration.proto";
import "gogoproto/gogo.proto";

option go_package = "config";
option (gogoproto.goproto_getters_all) = false;
option (gogoproto.equal_all) = false;
option (gogoproto.gostring_all) = false;

// redisquota adapter supports the rate limit quota using either fixed or
// rolling window algorithm. And it is using Redis as a shared data storage.
//
// Example configuration:
//
// ```yaml
// redisServerUrl: localhost:6379
// connectionPoolSize: 10
// quotas:
//   - name: requestCount.quota.istio-system
//     maxAmount: 50
//     validDuration: 60s
//     bucketDuration: 1s
//     rateLimitAlgorithm: ROLLING_WINDOW
//     overrides:
//       - dimensions:
//           destination: ratings
//           source: reviews
//         maxAmount: 12
//       - dimensions:
//           destination: reviews
//         maxAmount: 5
// ```
message Params {
  message Override {
    option (gogoproto.goproto_getters) = true;

    // The specific dimensions for which this override applies.
    // String representation of instance dimensions is used to check against configured dimensions.
    // dimensions should not be empty
    map <string, string> dimensions = 1 [(gogoproto.nullable) = false];

    // The upper limit for this quota override.
    // This value should be bigger than 0
    int64 max_amount = 2;
  }

  // Algorithms for rate-limiting:
  enum QuotaAlgorithm {
    // FIXED_WINDOW The fixed window approach can allow 2x peak specified rate, whereas the rolling-window doesn't.
    FIXED_WINDOW = 0;
    // ROLLING_WINDOW The rolling window algorithm's additional precision comes at the cost of increased redis resource usage.
    ROLLING_WINDOW = 1;
  }

  message Quota {
    option (gogoproto.goproto_getters) = true;

    // The name of the quota
    string name = 1;

    // The upper limit for this quota. max_amount should be bigger than 0
    int64 max_amount = 2;

    // The amount of time allocated quota remains valid before it is
    // automatically released. This is only meaningful for rate limit quotas.
    // value should be 0 < valid_duration
    google.protobuf.Duration valid_duration = 3 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true];

    // bucket_duration will be ignored if rate_limit_algorithm is FIXED_WINDOW
    // value should be 0 < bucket_duration < valid_duration
    google.protobuf.Duration bucket_duration = 4 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true];

    // Quota management algorithm. The default value is FIXED_WINDOW
    QuotaAlgorithm rate_limit_algorithm = 5;

    // Overrides associated with this quota.
    // The first matching override is applied.
    repeated Override overrides = 6;
  }

  // The set of known quotas. At least one quota configuration is required
  repeated Quota quotas = 1 [(gogoproto.nullable) = false];

  // Redis connection string <hostname>:<port number>
  // ex) localhost:6379
  string redis_server_url = 2;

  // Maximum number of idle connections to redis
  // Default is 10 connections per every CPU as reported by runtime.NumCPU.
  int64 connection_pool_size = 3;
}
