crabbucket/pgo
Types
pub type RemainingTokenCountFailure {
MustWaitUntil(next_reset_timestamp: Int)
PgoError(error: pgo.QueryError)
}
Constructors
-
MustWaitUntil(next_reset_timestamp: Int)
-
PgoError(error: pgo.QueryError)
pub type RemainingTokenCountSuccess {
HasRemainingTokens(
remaining_tokens: Int,
next_reset_timestamp: Int,
)
}
Constructors
-
HasRemainingTokens( remaining_tokens: Int, next_reset_timestamp: Int, )
pub type TokenBucketCleanerMessage(msg) {
ShutdownTokenBucketCleaner
StartTokenBucketCleaner(
Subject(TokenBucketCleanerMessage(msg)),
)
RunTokenBucketCleaner(Subject(TokenBucketCleanerMessage(msg)))
}
Constructors
-
ShutdownTokenBucketCleaner
-
StartTokenBucketCleaner(Subject(TokenBucketCleanerMessage(msg)))
-
RunTokenBucketCleaner(Subject(TokenBucketCleanerMessage(msg)))
pub type TokenBucketCleanerState(key) {
TokenBucketCleanerState(
conn: Connection,
sweep_interval_ms: Int,
)
}
Constructors
-
TokenBucketCleanerState(conn: Connection, sweep_interval_ms: Int)
Constants
pub const index_migration_sql: String
pub const schema_migration_sql: String
pub const table_migration_sql: String
Functions
pub fn create_and_start_cleaner(
conn: Connection,
sweep_interval_ms: Int,
) -> Subject(TokenBucketCleanerMessage(a))
Having our token buckets in a database table means there’s going to be cruft left behind. To mitigate this, a TokenBucketCleaner is an actor which periodically executes a SQL command to purge expired buckets.
sweep_interval_ms
describes how often the script should run,
in milliseconds.
The cleaner deletes 1,000-record segments at a time to help avoid writer contention in the database, and is hard-coded to only delete up to 10 segments (10,000 records) at a time, to avoid holding onto a pool connection for too long.
pub fn handle_cleaner_message(
message: TokenBucketCleanerMessage(a),
state: TokenBucketCleanerState(b),
) -> Next(
TokenBucketCleanerMessage(a),
TokenBucketCleanerState(b),
)
pub fn remaining_tokens_for_key(
conn: Connection,
key: String,
window_duration_ms: Int,
default_tokens: Int,
) -> Result(
RemainingTokenCountSuccess,
RemainingTokenCountFailure,
)
Takes an arbitrary key and window duration, inserting a record if non-existing.
Suggestion: you may wish to format your key such that it indicates
usage / purpose, value type, and value.
For instance, if you’re limiting a specific endpoint for a given user,
the key might look something like:
some_endpoint_name:user:12345
window_duration_milliseconds
describes the length of the time window
valid for a number of tokens.
For instance, a value of 1,000 with a default token count of 100 would mean
an action could occur 100 times per second.
Return should be either
HasRemainingTokens(remaining_tokens: Int, next_reset_timestamp: Int)
,
which indicates that an action may proceed and contains how many more times
the action may occur with the current window,
or it may be MustWaitUntil(next_reset_timestamp: Int)
,
which indicates that no tokens remain for this key and the next Unix
timestamp (in milliseconds) that the client must wait for.