Waiters¶
In any loop, you’ll probably want to wait between calls somehow, to prevent DDoSing your other services or 3rd party APIs. Tolerance come with 2 default raw waiters:
- SleepWaiter that simply wait using PHP’s usleep function
- NullWaiter that do not wait and it mainly used for tests
Once you are able to wait an amount of time, you may want to surcharge the waiters to apply different wait strategies such as an exponential back-off.
- The linear waiter simply waits a predefined amount of time.
- The exponential back-off waiter uses the well-known Exponential backoff algorithm to multiplicatively increase the amount of time of wait time.
- The count limited waiter simply adds a limit in the number of times it can be called.
- The rate limit waiter will wait the required amount of time to satisfy a rate limit.
Note
The Throttling component also come with a Rate Limited Operation Runner
SleepWaiter¶
This implementation will use PHP’s sleep
function to actually pause your process for a given amount of time.
1 2 3 4 5 6 | use Tolerance\Waiter\Waiter\SleepWaiter;
$waiter = new SleepWaiter();
// That will sleep for 500 milliseconds
$waiter->wait(0.5);
|
NullWaiter¶
The NullWaiter
won’t actually wait anything. This is usually used for the testing, you should be careful
using it in production.
1 2 3 | use Tolerance\Waiter\Waiter\NullWaiter;
$waiter = new NullWaiter();
|
Linear¶
How to simply always wait a predefined amount of time? There’s the linear waiter. The following example show how it can be used to have a waiter that will always wait 0.1 seconds.
1 2 3 4 | use Tolerance\Waiter\Waiter\SleepWaiter;
use Tolerance\Waiter\Waiter\Linear;
$waiter = new Linear(new SleepWaiter(), 0.1);
|
Exponential back-off¶
In a variety of computer networks, binary exponential backoff or truncated binary exponential backoff refers to an algorithm used to space out repeated retransmissions of the same block of data, often as part of network congestion avoidance.
The ExponentialBackOff
waiter decorates one of the raw waiters to add this additional exponential
wait time.
1 2 3 4 5 6 7 8 9 10 11 12 | use Tolerance\Waiter\Waiter\ExponentialBackOff;
use Tolerance\Waiter\Waiter\SleepWaiter;
// We use an initial collision number of 0
$waiter = new SleepWaiter();
$waitStrategy = new ExponentialBackOff($waiter, 0);
$waitStrategy->wait(); // 0.5s
$waitStrategy->wait(); // 1.5s
$waitStrategy->wait(); // 3.5s
// ...
|
Count limited¶
This decoration strategy defines a maximum amount of waits. Once this limit is reached, it will
throw the CountLimitReached
exception.
1 2 | // Wait for a maximum amount of 10 times
$waitingStrategy = new CountLimited($waitingStrategy, 10);
|
Rate Limit¶
Using the Rate Limit Waiter, you will just have to call the wait()
method of the waiter at the end of all your
iterations in a loop for instance, to ensure that each the iteration rate will match the rate limit you’ve defined.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | use Tolerance\Throttling\Rate\TimeRate;
use Tolerance\Throttling\RateLimit\LeakyBucket;
use Tolerance\Throttling\RateMeasureStorage\InMemoryStorage;
use Tolerance\Throttling\Waiter\RateLimitWaiter;
use Tolerance\Waiter\SleepWaiter;
$rate = new TimeRate(10, TimeRate::PER_SECOND);
$rateLimit = new LeakyBucket(new InMemoryStorage(), $rate);
$waiter = new RateLimitWaiter($rateLimit, new SleepWaiter());
for ($i = 0; $i < 100; $i++) {
echo microtime(true)."\n";
$waiter->wait('id');
}
|
The optional argument of the wait
method is the identifier of the operation you want to isolate. That means
that you can use the same waiter/rate limit for different type of operations if you want.
Time Out¶
This decoration strategy defines a time out to your operation execution. Once this time out is exceeded, it will
throw the TimedOutExceeded
exception.
1 2 | // Time out in 20 seconds
$waitingStrategy = new TimeOut($waitingStrategy, 20);
|