API platforms often enforce both a tenant-wide budget and a smaller per-user budget. A request is safe only when it fits both levels, and rejecting it must not partially consume either budget.
Design a HierarchicalQuotaLimiter class:
HierarchicalQuotaLimiter(int windowSize, int tenantLimit, int userLimit) configures fixed-window cost budgets.String allow(String tenantId, String userId, int cost, int timestamp) evaluates one request.
The window ID is integer division timestamp / windowSize. Timestamps are nondecreasing across calls. Within each window:
- Every tenant may consume at most
tenantLimit total units across all users. - Every
(tenantId, userId) pair may consume at most userLimit units. - Equal user IDs in different tenants are unrelated.
Check the projected tenant total first. Return "TENANT_LIMIT" if it would exceed the tenant limit. Otherwise check the projected user total and return "USER_LIMIT" if it would exceed the user limit. Rejections consume no units.
On success, charge both counters and return "ALLOWED:T:U", where T and U are the remaining tenant and user units after the charge.
Example 1:
Input:
Output:
Explanation: The failed user charge is atomic, leaving six tenant units for u2.
Example 2:
Input:
Output:
Explanation: The boundary starts a new window, and the two tenant-scoped users are independent.
Constraints
1 <= windowSize, tenantLimit, userLimit <= 10^91 <= tenantId.length, userId.length <= 100; IDs contain only letters, digits, _, and -.1 <= cost <= 10^90 <= timestamp <= 10^9- Timestamps are nondecreasing.
- At most
10^4 calls are made to allow.