vendor and env first commit
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Queue\Middleware;
|
||||
|
||||
use Illuminate\Cache\RateLimiter;
|
||||
use Illuminate\Cache\RateLimiting\Unlimited;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class RateLimited
|
||||
{
|
||||
/**
|
||||
* The rate limiter instance.
|
||||
*
|
||||
* @var \Illuminate\Cache\RateLimiter
|
||||
*/
|
||||
protected $limiter;
|
||||
|
||||
/**
|
||||
* The name of the rate limiter.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $limiterName;
|
||||
|
||||
/**
|
||||
* Indicates if the job should be released if the limit is exceeded.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $shouldRelease = true;
|
||||
|
||||
/**
|
||||
* Create a new middleware instance.
|
||||
*
|
||||
* @param string $limiterName
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($limiterName)
|
||||
{
|
||||
$this->limiter = Container::getInstance()->make(RateLimiter::class);
|
||||
|
||||
$this->limiterName = $limiterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the job.
|
||||
*
|
||||
* @param mixed $job
|
||||
* @param callable $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($job, $next)
|
||||
{
|
||||
if (is_null($limiter = $this->limiter->limiter($this->limiterName))) {
|
||||
return $next($job);
|
||||
}
|
||||
|
||||
$limiterResponse = $limiter($job);
|
||||
|
||||
if ($limiterResponse instanceof Unlimited) {
|
||||
return $next($job);
|
||||
}
|
||||
|
||||
return $this->handleJob(
|
||||
$job,
|
||||
$next,
|
||||
collect(Arr::wrap($limiterResponse))->map(function ($limit) {
|
||||
return (object) [
|
||||
'key' => md5($this->limiterName.$limit->key),
|
||||
'maxAttempts' => $limit->maxAttempts,
|
||||
'decaySeconds' => $limit->decaySeconds,
|
||||
];
|
||||
})->all()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a rate limited job.
|
||||
*
|
||||
* @param mixed $job
|
||||
* @param callable $next
|
||||
* @param array $limits
|
||||
* @return mixed
|
||||
*/
|
||||
protected function handleJob($job, $next, array $limits)
|
||||
{
|
||||
foreach ($limits as $limit) {
|
||||
if ($this->limiter->tooManyAttempts($limit->key, $limit->maxAttempts)) {
|
||||
return $this->shouldRelease
|
||||
? $job->release($this->getTimeUntilNextRetry($limit->key))
|
||||
: false;
|
||||
}
|
||||
|
||||
$this->limiter->hit($limit->key, $limit->decaySeconds);
|
||||
}
|
||||
|
||||
return $next($job);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not release the job back to the queue if the limit is exceeded.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function dontRelease()
|
||||
{
|
||||
$this->shouldRelease = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of seconds that should elapse before the job is retried.
|
||||
*
|
||||
* @param string $key
|
||||
* @return int
|
||||
*/
|
||||
protected function getTimeUntilNextRetry($key)
|
||||
{
|
||||
return $this->limiter->availableIn($key) + 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the object for serialization.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
return [
|
||||
'limiterName',
|
||||
'shouldRelease',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the object after unserialization.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __wakeup()
|
||||
{
|
||||
$this->limiter = Container::getInstance()->make(RateLimiter::class);
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Queue\Middleware;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Contracts\Redis\Factory as Redis;
|
||||
use Illuminate\Redis\Limiters\DurationLimiter;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
|
||||
class RateLimitedWithRedis extends RateLimited
|
||||
{
|
||||
use InteractsWithTime;
|
||||
|
||||
/**
|
||||
* The Redis factory implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Redis\Factory
|
||||
*/
|
||||
protected $redis;
|
||||
|
||||
/**
|
||||
* The timestamp of the end of the current duration by key.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $decaysAt = [];
|
||||
|
||||
/**
|
||||
* Create a new middleware instance.
|
||||
*
|
||||
* @param string $limiterName
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($limiterName)
|
||||
{
|
||||
parent::__construct($limiterName);
|
||||
|
||||
$this->redis = Container::getInstance()->make(Redis::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a rate limited job.
|
||||
*
|
||||
* @param mixed $job
|
||||
* @param callable $next
|
||||
* @param array $limits
|
||||
* @return mixed
|
||||
*/
|
||||
protected function handleJob($job, $next, array $limits)
|
||||
{
|
||||
foreach ($limits as $limit) {
|
||||
if ($this->tooManyAttempts($limit->key, $limit->maxAttempts, $limit->decaySeconds)) {
|
||||
return $this->shouldRelease
|
||||
? $job->release($this->getTimeUntilNextRetry($limit->key))
|
||||
: false;
|
||||
}
|
||||
}
|
||||
|
||||
return $next($job);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given key has been "accessed" too many times.
|
||||
*
|
||||
* @param string $key
|
||||
* @param int $maxAttempts
|
||||
* @param int $decaySeconds
|
||||
* @return bool
|
||||
*/
|
||||
protected function tooManyAttempts($key, $maxAttempts, $decaySeconds)
|
||||
{
|
||||
$limiter = new DurationLimiter(
|
||||
$this->redis, $key, $maxAttempts, $decaySeconds
|
||||
);
|
||||
|
||||
return tap(! $limiter->acquire(), function () use ($key, $limiter) {
|
||||
$this->decaysAt[$key] = $limiter->decaysAt;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of seconds that should elapse before the job is retried.
|
||||
*
|
||||
* @param string $key
|
||||
* @return int
|
||||
*/
|
||||
protected function getTimeUntilNextRetry($key)
|
||||
{
|
||||
return ($this->decaysAt[$key] - $this->currentTime()) + 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the object after unserialization.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __wakeup()
|
||||
{
|
||||
parent::__wakeup();
|
||||
|
||||
$this->redis = Container::getInstance()->make(Redis::class);
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Queue\Middleware;
|
||||
|
||||
class SkipIfBatchCancelled
|
||||
{
|
||||
/**
|
||||
* Process the job.
|
||||
*
|
||||
* @param mixed $job
|
||||
* @param callable $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($job, $next)
|
||||
{
|
||||
if (method_exists($job, 'batch') && $job->batch()?->cancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$next($job);
|
||||
}
|
||||
}
|
||||
+225
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Queue\Middleware;
|
||||
|
||||
use Illuminate\Cache\RateLimiter;
|
||||
use Illuminate\Container\Container;
|
||||
use Throwable;
|
||||
|
||||
class ThrottlesExceptions
|
||||
{
|
||||
/**
|
||||
* The developer specified key that the rate limiter should use.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $key;
|
||||
|
||||
/**
|
||||
* Indicates whether the throttle key should use the job's UUID.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $byJob = false;
|
||||
|
||||
/**
|
||||
* The maximum number of attempts allowed before rate limiting applies.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $maxAttempts;
|
||||
|
||||
/**
|
||||
* The number of seconds until the maximum attempts are reset.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $decaySeconds;
|
||||
|
||||
/**
|
||||
* The number of minutes to wait before retrying the job after an exception.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $retryAfterMinutes = 0;
|
||||
|
||||
/**
|
||||
* The callback that determines if the exception should be reported.
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
protected $reportCallback;
|
||||
|
||||
/**
|
||||
* The callback that determines if rate limiting should apply.
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
protected $whenCallback;
|
||||
|
||||
/**
|
||||
* The prefix of the rate limiter key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix = 'laravel_throttles_exceptions:';
|
||||
|
||||
/**
|
||||
* The rate limiter instance.
|
||||
*
|
||||
* @var \Illuminate\Cache\RateLimiter
|
||||
*/
|
||||
protected $limiter;
|
||||
|
||||
/**
|
||||
* Create a new middleware instance.
|
||||
*
|
||||
* @param int $maxAttempts
|
||||
* @param int $decaySeconds
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($maxAttempts = 10, $decaySeconds = 600)
|
||||
{
|
||||
$this->maxAttempts = $maxAttempts;
|
||||
$this->decaySeconds = $decaySeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the job.
|
||||
*
|
||||
* @param mixed $job
|
||||
* @param callable $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($job, $next)
|
||||
{
|
||||
$this->limiter = Container::getInstance()->make(RateLimiter::class);
|
||||
|
||||
if ($this->limiter->tooManyAttempts($jobKey = $this->getKey($job), $this->maxAttempts)) {
|
||||
return $job->release($this->getTimeUntilNextRetry($jobKey));
|
||||
}
|
||||
|
||||
try {
|
||||
$next($job);
|
||||
|
||||
$this->limiter->clear($jobKey);
|
||||
} catch (Throwable $throwable) {
|
||||
if ($this->whenCallback && ! call_user_func($this->whenCallback, $throwable)) {
|
||||
throw $throwable;
|
||||
}
|
||||
|
||||
if ($this->reportCallback && call_user_func($this->reportCallback, $throwable)) {
|
||||
report($throwable);
|
||||
}
|
||||
|
||||
$this->limiter->hit($jobKey, $this->decaySeconds);
|
||||
|
||||
return $job->release($this->retryAfterMinutes * 60);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a callback that should determine if rate limiting behavior should apply.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function when(callable $callback)
|
||||
{
|
||||
$this->whenCallback = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the prefix of the rate limiter key.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @return $this
|
||||
*/
|
||||
public function withPrefix(string $prefix)
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the number of minutes a job should be delayed when it is released (before it has reached its max exceptions).
|
||||
*
|
||||
* @param int $backoff
|
||||
* @return $this
|
||||
*/
|
||||
public function backoff($backoff)
|
||||
{
|
||||
$this->retryAfterMinutes = $backoff;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache key associated for the rate limiter.
|
||||
*
|
||||
* @param mixed $job
|
||||
* @return string
|
||||
*/
|
||||
protected function getKey($job)
|
||||
{
|
||||
if ($this->key) {
|
||||
return $this->prefix.$this->key;
|
||||
} elseif ($this->byJob) {
|
||||
return $this->prefix.$job->job->uuid();
|
||||
}
|
||||
|
||||
return $this->prefix.md5(get_class($job));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value that the rate limiter should be keyed by.
|
||||
*
|
||||
* @param string $key
|
||||
* @return $this
|
||||
*/
|
||||
public function by($key)
|
||||
{
|
||||
$this->key = $key;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the throttle key should use the job's UUID.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function byJob()
|
||||
{
|
||||
$this->byJob = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report exceptions and optionally specify a callback that determines if the exception should be reported.
|
||||
*
|
||||
* @param callable|null $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function report(?callable $callback = null)
|
||||
{
|
||||
$this->reportCallback = $callback ?? fn () => true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of seconds that should elapse before the job is retried.
|
||||
*
|
||||
* @param string $key
|
||||
* @return int
|
||||
*/
|
||||
protected function getTimeUntilNextRetry($key)
|
||||
{
|
||||
return $this->limiter->availableIn($key) + 3;
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Queue\Middleware;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Contracts\Redis\Factory as Redis;
|
||||
use Illuminate\Redis\Limiters\DurationLimiter;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
use Throwable;
|
||||
|
||||
class ThrottlesExceptionsWithRedis extends ThrottlesExceptions
|
||||
{
|
||||
use InteractsWithTime;
|
||||
|
||||
/**
|
||||
* The Redis factory implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Redis\Factory
|
||||
*/
|
||||
protected $redis;
|
||||
|
||||
/**
|
||||
* The rate limiter instance.
|
||||
*
|
||||
* @var \Illuminate\Redis\Limiters\DurationLimiter
|
||||
*/
|
||||
protected $limiter;
|
||||
|
||||
/**
|
||||
* Process the job.
|
||||
*
|
||||
* @param mixed $job
|
||||
* @param callable $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($job, $next)
|
||||
{
|
||||
$this->redis = Container::getInstance()->make(Redis::class);
|
||||
|
||||
$this->limiter = new DurationLimiter(
|
||||
$this->redis, $this->getKey($job), $this->maxAttempts, $this->decaySeconds
|
||||
);
|
||||
|
||||
if ($this->limiter->tooManyAttempts()) {
|
||||
return $job->release($this->limiter->decaysAt - $this->currentTime());
|
||||
}
|
||||
|
||||
try {
|
||||
$next($job);
|
||||
|
||||
$this->limiter->clear();
|
||||
} catch (Throwable $throwable) {
|
||||
if ($this->whenCallback && ! call_user_func($this->whenCallback, $throwable)) {
|
||||
throw $throwable;
|
||||
}
|
||||
|
||||
if ($this->reportCallback && call_user_func($this->reportCallback, $throwable)) {
|
||||
report($throwable);
|
||||
}
|
||||
|
||||
$this->limiter->acquire();
|
||||
|
||||
return $job->release($this->retryAfterMinutes * 60);
|
||||
}
|
||||
}
|
||||
}
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Queue\Middleware;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Contracts\Cache\Repository as Cache;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
|
||||
class WithoutOverlapping
|
||||
{
|
||||
use InteractsWithTime;
|
||||
|
||||
/**
|
||||
* The job's unique key used for preventing overlaps.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $key;
|
||||
|
||||
/**
|
||||
* The number of seconds before a job should be available again if no lock was acquired.
|
||||
*
|
||||
* @var \DateTimeInterface|int|null
|
||||
*/
|
||||
public $releaseAfter;
|
||||
|
||||
/**
|
||||
* The number of seconds before the lock should expire.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $expiresAfter;
|
||||
|
||||
/**
|
||||
* The prefix of the lock key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $prefix = 'laravel-queue-overlap:';
|
||||
|
||||
/**
|
||||
* Share the key across different jobs.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $shareKey = false;
|
||||
|
||||
/**
|
||||
* Create a new middleware instance.
|
||||
*
|
||||
* @param string $key
|
||||
* @param \DateTimeInterface|int|null $releaseAfter
|
||||
* @param \DateTimeInterface|int $expiresAfter
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($key = '', $releaseAfter = 0, $expiresAfter = 0)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->releaseAfter = $releaseAfter;
|
||||
$this->expiresAfter = $this->secondsUntil($expiresAfter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the job.
|
||||
*
|
||||
* @param mixed $job
|
||||
* @param callable $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($job, $next)
|
||||
{
|
||||
$lock = Container::getInstance()->make(Cache::class)->lock(
|
||||
$this->getLockKey($job), $this->expiresAfter
|
||||
);
|
||||
|
||||
if ($lock->get()) {
|
||||
try {
|
||||
$next($job);
|
||||
} finally {
|
||||
$lock->release();
|
||||
}
|
||||
} elseif (! is_null($this->releaseAfter)) {
|
||||
$job->release($this->releaseAfter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the delay (in seconds) to release the job back to the queue.
|
||||
*
|
||||
* @param \DateTimeInterface|int $releaseAfter
|
||||
* @return $this
|
||||
*/
|
||||
public function releaseAfter($releaseAfter)
|
||||
{
|
||||
$this->releaseAfter = $releaseAfter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not release the job back to the queue if no lock can be acquired.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function dontRelease()
|
||||
{
|
||||
$this->releaseAfter = null;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of seconds that can elapse before the lock is released.
|
||||
*
|
||||
* @param \DateTimeInterface|\DateInterval|int $expiresAfter
|
||||
* @return $this
|
||||
*/
|
||||
public function expireAfter($expiresAfter)
|
||||
{
|
||||
$this->expiresAfter = $this->secondsUntil($expiresAfter);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the prefix of the lock key.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @return $this
|
||||
*/
|
||||
public function withPrefix(string $prefix)
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the lock key should be shared across job classes.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function shared()
|
||||
{
|
||||
$this->shareKey = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lock key for the given job.
|
||||
*
|
||||
* @param mixed $job
|
||||
* @return string
|
||||
*/
|
||||
public function getLockKey($job)
|
||||
{
|
||||
return $this->shareKey
|
||||
? $this->prefix.$this->key
|
||||
: $this->prefix.get_class($job).':'.$this->key;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user