Skip to content

Commit

Permalink
Builder for locks.
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorotwell committed Aug 25, 2017
1 parent 92aff02 commit 3684f0c
Show file tree
Hide file tree
Showing 3 changed files with 249 additions and 15 deletions.
24 changes: 9 additions & 15 deletions src/Illuminate/Redis/Connections/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
namespace Illuminate\Redis\Connections;

use Closure;
use Illuminate\Redis\Limiters\DurationLimiter;
use Illuminate\Redis\Limiters\ConcurrencyLimiter;
use Illuminate\Redis\Limiters\DurationLimiterBuilder;
use Illuminate\Redis\Limiters\ConcurrencyLimiterBuilder;

/**
* @mixin \Predis\Client
Expand Down Expand Up @@ -32,30 +32,24 @@ abstract public function createSubscription($channels, Closure $callback, $metho
* Funnel a callback for a maximum number of simultaneous executions.
*
* @param string $name
* @param int $maxLocks
* @param int $seconds
* @param callable $callback
* @param int $timeout
* @return mixed
* @return \Illuminate\Redis\Limiters\ConcurrencyLimiterBuilder
*/
public function funnel($name, $maxLocks, $seconds, callable $callback, $timeout = 10)
public function funnel($name)
{
return new ConcurrencyLimiterBuilder($this, $name);

return (new ConcurrencyLimiter($this, $name, $maxLocks, $seconds))->block($timeout, $callback);
}

/**
* Throttle a callback for a maximum number of executions over a given duration.
*
* @param string $name
* @param int $maxLocks
* @param int $decay
* @param callable $callback
* @param int $timeout
* @return mixed
* @return \Illuminate\Redis\Limiters\DurationLimiterBuilder
*/
public function throttle($name, $maxLocks, $decay, callable $callback, $timeout = 10)
public function throttle($name)
{
return (new DurationLimiter($this, $name, $maxLocks, $decay))->block($timeout, $callback);
return new DurationLimiterBuilder($this, $name);
}

/**
Expand Down
120 changes: 120 additions & 0 deletions src/Illuminate/Redis/Limiters/ConcurrencyLimiterBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php

namespace Illuminate\Redis\Limiters;

use Illuminate\Support\InteractsWithTime;
use Illuminate\Contracts\Redis\LimiterTimeoutException;

class ConcurrencyLimiterBuilder
{
use InteractsWithTime;

/**
* The Redis connection.
*
* @var \Illuminate\Redis\Connections\Connection
*/
public $connection;

/**
* The name of the lock.
*
* @var string
*/
public $name;

/**
* The maximum number of entities that can hold the lock at the same time.
*
* @var int
*/
public $maxLocks;

/**
* The number of seconds to maintain the lock until it is automatically released.
*
* @var int
*/
public $releaseAfter = 60;

/**
* The amount of time to block until a lock is available.
*
* @var int
*/
public $timeout = 3;

/**
* Create a new builder instance.
*
* @param \Illuminate\Redis\Connetions\Connection $connection
* @param string $name
* @return void
*/
public function __construct($connection, $name)
{
$this->name = $name;
$this->connection = $connection;
}

/**
* Set the maximum number of locks that can obtained per time window.
*
* @param int $maxLocks
* @return $this
*/
public function limit($maxLocks)
{
$this->maxLocks = $maxLocks;

return $this;
}

/**
* Set the number of seconds until the lock will be released.
*
* @param int $releaseAfter
* @return $this
*/
public function releaseAfter($releaseAfter)
{
$this->releaseAfter = $this->secondsUntil($releaseAfter);

return $this;
}

/**
* Set the amount of time to block until a lock is available.
*
* @param int $timeout
* @return $this
*/
public function block($timeout)
{
$this->timeout = $timeout;

return $this;
}

/**
* Execute the given callback if a lock is obtained, otherise call the failure callback.
*
* @param callable $callback
* @param callable $failure
* @return mixed
*/
public function then(callable $callback, callable $failure = null)
{
try {
return (new ConcurrencyLimiter(
$this->connection, $this->name, $this->maxLocks, $this->releaseAfter
))->block($this->timeout, $callback);
} catch (LimiterTimeoutException $e) {
if ($failure) {
return $failure($e);
}

throw $e;
}
}
}
120 changes: 120 additions & 0 deletions src/Illuminate/Redis/Limiters/DurationLimiterBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php

namespace Illuminate\Redis\Limiters;

use Illuminate\Support\InteractsWithTime;
use Illuminate\Contracts\Redis\LimiterTimeoutException;

class DurationLimiterBuilder
{
use InteractsWithTime;

/**
* The Redis connection.
*
* @var \Illuminate\Redis\Connections\Connection
*/
public $connection;

/**
* The name of the lock.
*
* @var string
*/
public $name;

/**
* The maximum number of locks that can obtained per time window.
*
* @var int
*/
public $maxLocks;

/**
* The amount of time the lock window is maintained.
*
* @var int
*/
public $decay;

/**
* The amount of time to block until a lock is available.
*
* @var int
*/
public $timeout = 3;

/**
* Create a new builder instance.
*
* @param \Illuminate\Redis\Connetions\Connection $connection
* @param string $name
* @return void
*/
public function __construct($connection, $name)
{
$this->name = $name;
$this->connection = $connection;
}

/**
* Set the maximum number of locks that can obtained per time window.
*
* @param int $maxLocks
* @return $this
*/
public function allow($maxLocks)
{
$this->maxLocks = $maxLocks;

return $this;
}

/**
* Set the amount of time the lock window is maintained.
*
* @param int $decay
* @return $this
*/
public function every($decay)
{
$this->decay = $this->secondsUntil($decay);

return $this;
}

/**
* Set the amount of time to block until a lock is available.
*
* @param int $timeout
* @return $this
*/
public function block($timeout)
{
$this->timeout = $timeout;

return $this;
}

/**
* Execute the given callback if a lock is obtained, otherise call the failure callback.
*
* @param callable $callback
* @param callable $failure
* @return mixed
*/
public function then(callable $callback, callable $failure = null)
{
try {
return (new DurationLimiter(
$this->connection, $this->name, $this->maxLocks, $this->decay
))->block($this->timeout, $callback);
} catch (LimiterTimeoutException $e) {
if ($failure) {
return $failure($e);
}

throw $e;
}
}
}

0 comments on commit 3684f0c

Please sign in to comment.