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.
This project is open source and available under the MIT License.
- PHP
^8.0
(Tested up to8.4
) - PDO PHP extension
- JSON PHP extension
composer require bayfrontmedia/leaky-bucket
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());
}
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.
- 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
Description:
Checks if this bucket ID already exists in storage.
Parameters:
- None
Returns:
- (bool)
Example:
if ($bucket->exists()) {
// Do something
}
Description:
Saves the bucket.
Parameters:
- None
Returns:
- (self)
Throws:
Bayfront\LeakyBucket\AdapterException
Example:
try {
$bucket->save();
} catch (AdapterException $e) {
die($e->getMessage());
}
Description:
Returns entire bucket contents.
Parameters:
- None
Returns:
- (array)
Example:
$contents = $bucket->get();
Description:
Reset all bucket information and data.
Parameters:
- None
Returns:
- (self)
Example:
$bucket->reset();
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());
}
Description:
Checks if bucket is full.
Parameters:
- None
Returns:
- (bool)
Example:
if ($bucket->isFull()) {
// Do something
}
Description:
Returns the total bucket capacity.
Parameters:
- None
Returns:
- (int)
Example:
echo $bucket->getCapacity();
Description:
Returns the number of drops in the bucket.
Parameters:
- None
Returns:
- (float)
Example:
echo $bucket->getCapacityUsed();
Description:
Returns the remaining bucket capacity.
Parameters:
- None
Returns:
- (float)
Example:
echo $bucket->getCapacityRemaining();
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
}
Description:
Returns the number of drops per second the bucket will leak.
Parameters:
- None
Returns:
- (float)
Example:
echo $bucket->getLeakPerSecond();
Description:
Returns the number of seconds required to leak one drop.
Parameters:
- None
Returns:
- (float)
Example:
echo $bucket->getSecondsPerDrop();
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();
Description:
Returns the number of seconds until bucket would be empty.
Parameters:
- None
Returns:
- (float)
Example:
echo $bucket->getSecondsUntilEmpty();
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();
Description:
Returns the bucket's last timestamp.
Parameters:
- None
Returns:
- (int)
Example:
echo $bucket->getLastTime();
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());
}
Description:
Updates the bucket by calculating how many drops to leak since it's last timestamp.
Parameters:
- None
Returns:
- (self)
Example:
$bucket->leak();
Description:
Spills a given number of drops from the bucket.
Parameters:
$drops = 1
(int)
Returns:
- (self)
Example:
$bucket->spill(5);
Description:
Dumps (empties) all drops from the bucket in excess of its capacity.
Parameters:
- None
Returns:
- (self)
Example:
$bucket->overflow();
Description:
Dumps (empties) all drops from the bucket.
Parameters:
- None
Returns:
- (self)
Example:
$bucket->dump();
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
}
Description:
Sets additional data for this bucket in dot notation.
Parameters:
$key
(string)$value
(mixed)
Returns:
- (self)
Example:
$bucket->setData('client_id', 5);
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');
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');