Meta Graph API services often enforce per-client request limits using a token bucket. Implement a secure in-memory rate limiter that validates a request signature and then decides whether the request is allowed under a per-key token bucket.
Write a function that processes a list of request events in timestamp order. Each event contains timestamp, key, cost, and signature. A request is valid only if its signature matches the expected signature for that key. Invalid signatures must be rejected and must not consume tokens. Valid requests consume cost tokens only if enough tokens are available at that timestamp.
Input:
capacity: integer bucket sizerefill_rate: integer tokens added per secondsecrets: map from string key to string secretrequests: list of [timestamp, key, cost, signature]Output:
The expected signature for a request is the string:
key + ":" + str(timestamp) + ":" + str(cost) + ":" + secret
Each key has its own bucket. Buckets start full at capacity. On each request, refill based on elapsed whole or fractional seconds since that key's previous valid request processing time, capped at capacity.
Example 1
capacity = 5, refill_rate = 1, secrets = {"app1": "s1"}, requests = [[0, "app1", 3, "app1:0:3:s1"], [1, "app1", 3, "app1:1:3:s1"]][true, true]Example 2
capacity = 4, refill_rate = 2, secrets = {"app1": "s1"}, requests = [[0, "app1", 2, "bad"], [0.5, "app1", 3, "app1:0.5:3:s1"]][false, true]1 <= capacity <= 10^61 <= refill_rate <= 10^61 <= len(requests) <= 10^50 <= timestamp <= 10^91 <= cost <= 10^6