bayfrontmedia / leaky-bucket
Framework-agnostic throttling using the leaky bucket algorithm.
Requires
- php: ^8.0
- ext-json: *
- ext-pdo: *
- bayfrontmedia/php-array-helpers: ^2.0
- league/flysystem: ^3.14
README
Framework-agnostic throttling using the leaky bucket algorithm.
A bucket has a defined capacity and leak rate per minute. Buckets can also store additional arbitrary data.
License
This project is open source and available under the MIT License.
Author
Requirements
- PHP
^8.0
- PDO PHP extension
- JSON PHP extension
Installation
composer require bayfrontmedia/leaky-bucket
Usage
Storage adapter
A Bayfront\LeakyBucket\ApadpterInterface
must be passed to the Bayfront\LeakyBucket\Bucket
constructor.
There are a variety of storage adapters available, each with their own required configuration.
Flysystem
The Flysystem
adapter allows you to use a Flysystem League\Flysystem\Filesystem
v3 instance for bucket storage.
use Bayfront\LeakyBucket\Adapters\Flysystem;
$adapter = new Flysystem($filesystem, '/root_path');
Local
The Local
adapter allows you to store buckets locally using native PHP.
use Bayfront\LeakyBucket\Adapters\Local;
$adapter = new Local('/root_path');
PDO
The PDO
adapter allows you to use a \PDO
instance for bucket storage into a database.
The PDO
adapter will create/use a table named "buckets" unless otherwise specified in the constructor.
use Bayfront\LeakyBucket\Adapters\PDO;
$adapter = new PDO($dbh, 'table_to_use');
Use the up
method to create the necessary database table to be used by this adapter.
Use the down
method to remove the database table.
These methods throw a Bayfront\LeakyBucket\AdapterException
exception.
try {
$adapter->up();
} catch (AdapterException $e) {
die($e->getMessage());
}
Start using Leaky Bucket
Once your adapter has been created, it can be used with Leaky Bucket. In addition, an optional settings array can be passed to the constructor. The default settings are shown below.
use Bayfront\LeakyBucket\AdapterException;
use Bayfront\LeakyBucket\BucketException;
use Bayfront\LeakyBucket\Bucket;
// Create/retrieve a bucket with a given ID
try {
$bucket = new Bucket('bucket_id', $adapter, [
'capacity' => 10, // Total drop capacity
'leak' => 10 // Number of drops to leak per minute
]);
} catch (AdapterException | BucketException $e) {
die($e->getMessage());
}
// Work with the bucket
$bucket->leak();
if ($bucket->hasCapacity()) {
try {
$bucket->fill()->save();
} catch (AdapterException $e) {
die($e->getMessage());
}
}
NOTE:
Be sure to leak()
the bucket before attempting to do any calculations regarding its capacity.
Also, the save()
method must be used to store the current bucket settings for future use.
Public methods
- exists
- save
- get
- reset
- delete
- isFull
- getCapacity
- getCapacityUsed
- getCapacityRemaining
- hasCapacity
- getLeakPerSecond
- getSecondsPerDrop
- getSecondsUntilCapacity
- getSecondsUntilEmpty
- touch
- getLastTime
- fill
- leak
- spill
- overflow
- dump
- hasData
- setData
- getData
- forgetData
exists
Description:
Checks if this bucket ID already exists in storage.
Parameters:
- None
Returns:
- (bool)
Example:
if ($bucket->exists()) {
// Do something
}
save
Description:
Saves the bucket.
Parameters:
- None
Returns:
- (self)
Throws:
Bayfront\LeakyBucket\AdapterException
Example:
try {
$bucket->save();
} catch (AdapterException $e) {
die($e->getMessage());
}
get
Description:
Returns entire bucket contents.
Parameters:
- None
Returns:
- (array)
Example:
$contents = $bucket->get();
reset
Description:
Reset all bucket information and data.
Parameters:
- None
Returns:
- (self)
Example:
$bucket->reset();
delete
Description:
Resets bucket and deletes the file in storage.
Parameters:
- None
Returns:
- (self)
Throws:
Bayfront\LeakyBucket\AdapterException
Example:
try {
$bucket->delete();
} catch (AdapterException $e) {
die($e->getMessage());
}
isFull
Description:
Checks if bucket is full.
Parameters:
- None
Returns:
- (bool)
Example:
if ($bucket->isFull()) {
// Do something
}
getCapacity
Description:
Returns the total bucket capacity.
Parameters:
- None
Returns:
- (int)
Example:
echo $bucket->getCapacity();
getCapacityUsed
Description:
Returns the number of drops in the bucket.
Parameters:
- None
Returns:
- (float)
Example:
echo $bucket->getCapacityUsed();
getCapacityRemaining
Description:
Returns the remaining bucket capacity.
Parameters:
- None
Returns:
- (float)
Example:
echo $bucket->getCapacityRemaining();
hasCapacity
Description:
Checks if bucket has the capacity fo fill by a given number of drops.
Parameters:
$drops = 1
(int)
Returns:
- (bool)
Example:
if ($bucket->hasCapacity(5)) {
// Do something
}
getLeakPerSecond
Description:
Returns the number of drops per second the bucket will leak.
Parameters:
- None
Returns:
- (float)
Example:
echo $bucket->getLeakPerSecond();
getSecondsPerDrop
Description:
Returns the number of seconds required to leak one drop.
Parameters:
- None
Returns:
- (float)
Example:
echo $bucket->getSecondsPerDrop();
getSecondsUntilCapacity
Description:
Returns the number of seconds until bucket has capacity for number of drops.
Returns 0
if bucket has capacity.
Parameters:
$drops = 1
(int)
Returns:
- (float)
Example:
echo $bucket->getSecondsPerDrop();
getSecondsUntilEmpty
Description:
Returns the number of seconds until bucket would be empty.
Parameters:
- None
Returns:
- (float)
Example:
echo $bucket->getSecondsUntilEmpty();
touch
Description:
Manually update the bucket's timestamp.
The bucket's timestamp is automatically updated when any of the following methods are called:
Parameters:
- None
Returns:
- (self)
Example:
$bucket->touch();
getLastTime
Description:
Returns the bucket's last timestamp.
Parameters:
- None
Returns:
- (int)
Example:
echo $bucket->getLastTime();
fill
Description:
Fills the bucket with a given number of drops.
If not allowed to overflow, and the bucket does not have the required capacity,
a Bayfront\LeakyBucket\BucketException
will be thrown.
Otherwise, the bucket will be allowed to overflow.
Parameters:
$drops = 1
(int)$allow_overflow = false
(bool)
Returns:
- (self)
Throws:
Bayfront\LeakyBucket\BucketException
Example:
try {
$bucket->fill();
} catch (BucketException $e) {
die($e->getMessage());
}
leak
Description:
Updates the bucket by calculating how many drops to leak since it's last timestamp.
Parameters:
- None
Returns:
- (self)
Example:
$bucket->leak();
spill
Description:
Spills a given number of drops from the bucket.
Parameters:
$drops = 1
(int)
Returns:
- (self)
Example:
$bucket->spill(5);
overflow
Description:
Dumps (empties) all drops from the bucket in excess of its capacity.
Parameters:
- None
Returns:
- (self)
Example:
$bucket->overflow();
dump
Description:
Dumps (empties) all drops from the bucket.
Parameters:
- None
Returns:
- (self)
Example:
$bucket->dump();
hasData
Description:
Checks if this bucket contains any additional data, or a specific key in dot notation.
Parameters:
$key = NULL
(string|null): IfNULL
, checks if any additional data exists
Returns:
- (bool)
Example:
if ($bucket->hasData('client_id')) {
// Do something
}
setData
Description:
Sets additional data for this bucket in dot notation.
Parameters:
$key
(string)$value
(mixed)
Returns:
- (self)
Example:
$bucket->setData('client_id', 5);
getData
Description:
Returns this bucket's additional data key in dot notation, or an optional default value if not found.
Parameters:
$key = NULL
(string|null): Returns the entire data array whenNULL
$default = NULL
(mixed)
Returns:
- (mixed)
Example:
$client_id = $bucket->getData('client_id');
forgetData
Description:
Removes additional data key in dot notation for this bucket.
Parameters:
$key = NULL
(string|null): Removes the entire data array whenNULL
Returns:
- (self)
Example:
$bucket->forgetData('client_id');