go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/server/quota/quotapb/service.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 "google/protobuf/duration.proto"; 8 import "google/protobuf/timestamp.proto"; 9 10 import "validate/validate.proto"; 11 12 import "go.chromium.org/luci/server/quota/quotapb/account.proto"; 13 import "go.chromium.org/luci/server/quota/quotapb/ids.proto"; 14 import "go.chromium.org/luci/server/quota/quotapb/op.proto"; 15 import "go.chromium.org/luci/server/quota/quotapb/policy_config.proto"; 16 17 option go_package = "go.chromium.org/luci/server/quota/quotapb"; 18 19 package go.chromium.org.luci.server.quota.quotapb; 20 21 // A GetAccountsRequest is a request to fetch multiple Account entries. 22 // 23 // You must have the `quota.accounts.read` permission in the realm of all the 24 // indicated accounts. 25 message GetAccountsRequest { 26 // A list of specific accounts to fetch. 27 repeated AccountID account = 1; 28 } 29 30 // GetAccountsResponse is the response to GetAccounts() 31 message GetAccountsResponse { 32 message AccountState { 33 AccountID id = 1[ 34 (validate.rules).message.required = true 35 ]; 36 37 // The current account, if the account exists, unset otherwise. 38 Account account = 2; 39 40 // Contains the effective balance for the account, given its current 41 // refill policy and updated_ts. 42 int64 projected_balance = 3; 43 } 44 repeated AccountState accounts = 1; 45 } 46 47 // ApplyOpsRequest allows a number of quota operations to be performed atomically. 48 message ApplyOpsRequest { 49 // If provided, the service will de-duplicate the request based on this ID, 50 // namespaced to the calling user. 51 // 52 // Once this ApplyOpsRequest successfully applies once, futher ApplyOpsRequests 53 // within `request_id_ttl` will immediately return as successful. 54 string request_id = 1; 55 56 // Must be set, and positive, if request_id is set. 57 // 58 // If this is omitted, the request_id_ttl is 2 hours. 59 // 60 // If this is zero, the request_id_ttl is infinite. 61 google.protobuf.Duration request_id_ttl = 2 [ 62 (validate.rules).duration.required = false, 63 (validate.rules).duration.gt.seconds = 0 64 ]; 65 66 // The operations to apply. 67 repeated Op ops = 3; 68 } 69 70 // OpResult contains the summary of applying a single Op as part of an 71 // ApplyOpsRequest. 72 // 73 // Note that `previous_balance` and `balance` are first in this message to make 74 // the success-case encoding of an OpResult with non-zero balances as compact as 75 // possible (will be represented by a 2-number msgpack array, rather than 76 // a msgpack object). 77 message OpResult { 78 // This will be set to the balance of the Account after the SUCCESS-ful 79 // operation. 80 int64 new_balance = 1; 81 82 // If the account already existed, this will be set to the balance observed at 83 // the start of this Operation (after applying refill under existing policy, 84 // if the account had one set). If the account did not previously exist, this 85 // will be 0, even if the Policy in this Op would set a default value. 86 // 87 // Note that if the same account is used for multiple operations in the same 88 // RPC, for the N'th operation on account X, this will have the N-1'th 89 // `balance` value. 90 int64 previous_balance = 2; 91 92 enum AccountStatus { 93 // This Op updated an existing account. 94 ALREADY_EXISTS = 0; 95 96 // This Op resulted in the creation of an account. 97 CREATED = 1; 98 99 // This Op found an existing, unreadable, account, and the account was 100 // recreated (as if it were missing). 101 // 102 // Note that this is supposed to be a rare condition, and will be monitored 103 // on the server side. If seen at elevated rates, this is likely alertable. 104 RECREATED = 2; 105 } 106 AccountStatus account_status = 3; 107 108 enum OpStatus { 109 // The Operation was successful. 110 SUCCESS = 0; 111 112 // There was an otherwise-unclassified error while applying this operation. 113 ERR_UNKNOWN = 1; 114 115 // The Op failed because it would bring the Account balance above the policy 116 // limit. 117 ERR_OVERFLOW = 2; 118 119 // The Op failed because it would bring the Account balance below 0. 120 ERR_UNDERFLOW = 3; 121 122 // The Op failed because it referred to a Policy which doesn't exist. 123 ERR_UNKNOWN_POLICY = 4; 124 125 // The Op failed because it applied to a non-existant Account and no Policy 126 // was given. 127 ERR_MISSING_ACCOUNT = 5; 128 129 // The Op failed because it used relative_to=DEFAULT or LIMIT, but the Account 130 // had no Policy attached to it, or if the Op did not include the 131 // IGNORE_POLICY_BOUNDS option. 132 ERR_POLICY_REQUIRED = 6; 133 } 134 // Status for this operation. 135 OpStatus status = 4; 136 137 // Extra context for `status` as english text. Usually unset, but will be most 138 // frequently set for UNKNOWN errors. 139 string status_msg = 5; 140 141 // When WITH_POLICY_LIMIT_DELTA option is used, previous_balance_adjusted is 142 // set to the previous balance + delta (where delta is the difference between 143 // the new Policy.limit and the old Policy.limit). If WITH_POLICY_LIMIT_DELTA 144 // is not set or if there is no change in policy_ref, or if the account has no 145 // existing policy_ref, previous_balance_adjusted is same as previous_balance. 146 int64 previous_balance_adjusted = 6; 147 } 148 149 message ApplyOpsResponse { 150 // This is a sequence of results, one per op in the original ApplyOpsRequest. 151 // 152 // NOTE: The caller must observe the `status` field of each result in order to 153 // determine if this request was successful. 154 // 155 // If any result contains a non-SUCCESS `status`, NONE of the operations have 156 // been saved. 157 repeated OpResult results = 1; 158 159 // The time this ApplyOpsResponse was created, according to the quota state. 160 // Note that for deduplicated requests, this could be fairly old (assuming the 161 // original request was made a while ago). 162 google.protobuf.Timestamp originally_set = 2; 163 } 164 165 message WritePolicyConfigRequest { 166 // If id.version_kind != Manual, id.version will be ignored. 167 PolicyConfigID id = 1[ 168 (validate.rules).message.required = true 169 ]; 170 171 PolicyConfig policy_config = 2 [ 172 (validate.rules).message.required = true 173 ]; 174 } 175 176 message WritePolicyConfigResponse { 177 // Returns the computed hash version (or responds with the input `version` if 178 // using an application-specific version) 179 string version = 1; 180 } 181 182 // Admin exposes an administration API quota state. 183 service Admin { 184 // GetAccounts returns the indicated Accounts. 185 rpc GetAccounts(GetAccountsRequest) returns (GetAccountsResponse); 186 187 // ApplyOps updates the available resources with the provided operations. 188 rpc ApplyOps(ApplyOpsRequest) returns (ApplyOpsResponse); 189 190 // WritePolicyConfig ingests the given PolicyConfig into the database. 191 rpc WritePolicyConfig(WritePolicyConfigRequest) returns (WritePolicyConfigResponse); 192 193 // TODO: ScanAccounts (w/ pattern) 194 // TODO: GetPolicyConfigs 195 // TODO: ScanPolicyConfigs (w/ pattern) 196 // TODO: PurgePolicyConfigs 197 }