go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/server/quota/quotapb/policy.proto (about)

     1  // Copyright 2022 The LUCI Authors. All rights reserved.
     2  // Use of this source code is governed under the Apache License, Version 2.0
     3  // that can be found in the LICENSE file.
     4  
     5  syntax = "proto3";
     6  
     7  import "validate/validate.proto";
     8  import "google/protobuf/duration.proto";
     9  
    10  option go_package = "go.chromium.org/luci/server/quota/quotapb";
    11  
    12  package go.chromium.org.luci.server.quota.quotapb;
    13  
    14  // A Policy represents a single quota policy.
    15  //
    16  // A single Policy will typically be used to govern many Accounts.
    17  //
    18  // Policies are always loaded into the database within a PolicyConfig.
    19  message Policy {
    20    // The number of resources to assign to an Account when first accessed under
    21    // this Policy.
    22    //
    23    // Must be <= `limit`.
    24    uint64 default = 1 [
    25      (validate.rules).uint64.lte = 9007199254740991
    26    ];
    27  
    28    // The maximum balance of Accounts managed under this Policy.
    29    //
    30    // Operations with a positive delta will be capped to this value, unless they
    31    // specify `POLICY_HARD_LIMIT`, in which case exceeding this limit will be an
    32    // error.
    33    //
    34    // If this policy has a positive refill, accounts with this policy will
    35    // gradually fill to this limit over time (but will never refill past it).
    36    //
    37    // NOTE: When assigning a new Policy to an existing Account it's possible for
    38    // an Account balance to exceed this value.
    39    //
    40    // For example, say an Account had a balance of 100 under a Policy with
    41    // a limit of 100, but then you set a new Policy with a limit of 50. In this
    42    // case, the Account balance remains at 100. However, the Account would not
    43    // gain any additional refill under the new Policy until it was brought below
    44    // 50 (the new limit).
    45    //
    46    // This is done because applications using the quota library may not have full
    47    // consistency with their Policy choice (e.g. they may choose a Policy based
    48    // on group membership, which is volatile, or some application nodes may have
    49    // gotten configuration to use a new Policy version while others haven't).
    50    uint64 limit = 2 [
    51      (validate.rules).uint64.lte = 9007199254740991
    52    ];
    53  
    54    // Refill describes how Accounts under this Policy refill (or drain) over
    55    // time.
    56    //
    57    // The Refill process mimics a cron, starting at UTC midnight + offset, waking
    58    // up every `interval` seconds to add `units` to the Account balance (up to
    59    // `limit`). This refill operation only happens when an Account is actually
    60    // interacted with, however.
    61    message Refill {
    62      // The number of units to add to the Account banance every `interval`.
    63      //
    64      // The refill process is discrete; From T0..T0+interval, none of
    65      // these units will appear in the Account balance. At T0+interval, all
    66      // the units will be added.
    67      //
    68      // Note that it's permitted to have a negative refill `units` to have
    69      // Account balances drain back to 0 over time.
    70      //
    71      // It's not permitted for the units to be 0 (just omit the Refill message
    72      // entirely in that case).
    73      int64 units = 1 [(validate.rules).int64 = {
    74        gte: -9007199254740991
    75        not_in: 0
    76        lte:  9007199254740991
    77      }];
    78  
    79      // The number of seconds between refill events, synchronized to UTC midnight
    80      // + `offset`.
    81      //
    82      // If this is 0 and `units` is positive, the Account will be treated as if
    83      // it always has `limit` quota.
    84      //
    85      // It is an error for this to be 0 with negative `units`. To achieve this,
    86      // just make a Policy with a limit of 0 and no Refill.
    87      //
    88      // Refill events occur synchronized to "midnight" in UTC. So if you set this
    89      // to 60, then each minute-after-UTC-midnight, the Account will gain
    90      // `units`. This synchronization makes quota Account refill more
    91      // predictable.
    92      //
    93      // The offset from UTC is currently configed on the Policy (i.e. to support
    94      // policies which are synched with different time zones), but this
    95      // presumably could instead be configured on a per-Account basis, if it were
    96      // needed.
    97      //
    98      // This MUST evenly divide 24h (86400). For example, an interval of 71 is
    99      // NOT OK because it would divide the day into 1216.9 intervals, meaning
   100      // that the refresh 'cycle' could not correctly reset at midnight every day.
   101      // An interval of 72 IS ok though, because it evenly divides the day into
   102      // 1200 refresh periods.
   103      uint32 interval = 2 [
   104        (validate.rules).uint32.lte = 86400  // 24h
   105      ];
   106  
   107      // An offset from UTC midnight. This will be used to establish when the
   108      // associated Accounts 'start their day', and can be used to implement
   109      // a rudimentary timezone alignment for quota Accounts.
   110      uint32 offset = 3 [
   111        (validate.rules).uint32.lte = 86400  // 24h
   112      ];
   113    }
   114    Refill refill = 3;
   115  
   116    enum Options {
   117      NO_OPTIONS = 0;
   118  
   119      // Indicates that this Policy covers a resource type which represents an
   120      // absolute quantity (e.g. number of builds in flight, current amount of
   121      // storage used, etc.). Accounts flagged with this option cannot be manually
   122      // manipulated via the Admin API, even with `quota.accounts.write`
   123      // permission. Applications which need to expose 'reset' functionality for
   124      // these should expose their own endpoints for this (or, ideally, don't
   125      // allow these Accounts to get out of sync with reality in the first place
   126      // :))
   127      ABSOLUTE_RESOURCE = 1;
   128    }
   129    // Bitwise-OR of Options values.
   130    int32 options = 4;
   131  
   132    // The amount of time that Accounts created with this Policy should persist
   133    // after being written. Each Op on the Account refreshes the timeout.
   134    //
   135    // This could be used to create temporary quota Accounts based on e.g. IP
   136    // address which automatically garbage collect after a certain time.
   137    //
   138    // A value of 0 means an 'infinite' Account lifetime (the default).
   139    // It's recommended to pick some very large value for this rather than 0, to
   140    // allow Redis to prune old Accounts when it needs to do garbage collection.
   141    google.protobuf.Duration lifetime = 5;
   142  }