Browse Source
- Increase frequency of lock tries for `yii\mutex\FileMutex::acquireLock()` when $timeout is provided (rob006) - Add support for `$timeout` in `yii\mutex\PgsqlMutex::acquire()`tags/2.0.16
Robert Korulczyk
6 years ago
committed by
Alexander Makarov
7 changed files with 179 additions and 26 deletions
@ -0,0 +1,40 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yii\mutex; |
||||
|
||||
use Closure; |
||||
|
||||
/** |
||||
* Trait RetryAcquireTrait. |
||||
* |
||||
* @author Robert Korulczyk <robert@korulczyk.pl> |
||||
* @internal |
||||
*/ |
||||
trait RetryAcquireTrait |
||||
{ |
||||
/** |
||||
* @var int Number of milliseconds between each try in [[acquire()]] until specified timeout times out. |
||||
* By default it is 50 milliseconds - it means that [[acquire()]] may try acquire lock up to 20 times per second. |
||||
* @since 2.0.16 |
||||
*/ |
||||
public $retryDelay = 50; |
||||
|
||||
|
||||
private function retryAcquire($timeout, Closure $callback) |
||||
{ |
||||
$start = microtime(true); |
||||
do { |
||||
if ($callback()) { |
||||
return true; |
||||
} |
||||
usleep($this->retryDelay * 1000); |
||||
} while (microtime(true) - $start < $timeout); |
||||
|
||||
return false; |
||||
} |
||||
} |
@ -0,0 +1,49 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yiiunit\framework\mutex; |
||||
|
||||
use Yii; |
||||
use yii\base\InvalidConfigException; |
||||
use yiiunit\framework\mutex\mocks\DumbMutex; |
||||
use yiiunit\TestCase; |
||||
|
||||
/** |
||||
* Class RetryAcquireTraitTest. |
||||
* |
||||
* @group mutex |
||||
* |
||||
* @author Robert Korulczyk <robert@korulczyk.pl> |
||||
*/ |
||||
class RetryAcquireTraitTest extends TestCase |
||||
{ |
||||
/** |
||||
* @throws InvalidConfigException |
||||
*/ |
||||
public function testRetryAcquire() |
||||
{ |
||||
$mutexName = __FUNCTION__; |
||||
$mutexOne = $this->createMutex(); |
||||
$mutexTwo = $this->createMutex(); |
||||
|
||||
$this->assertTrue($mutexOne->acquire($mutexName)); |
||||
$this->assertFalse($mutexTwo->acquire($mutexName, 1)); |
||||
|
||||
$this->assertSame(20, $mutexTwo->attemptsCounter); |
||||
} |
||||
|
||||
/** |
||||
* @return DumbMutex |
||||
* @throws InvalidConfigException |
||||
*/ |
||||
private function createMutex() |
||||
{ |
||||
return Yii::createObject([ |
||||
'class' => DumbMutex::className(), |
||||
]); |
||||
} |
||||
} |
@ -0,0 +1,55 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yiiunit\framework\mutex\mocks; |
||||
|
||||
use yii\mutex\Mutex; |
||||
use yii\mutex\RetryAcquireTrait; |
||||
|
||||
/** |
||||
* Class DumbMutex. |
||||
* |
||||
* @author Robert Korulczyk <robert@korulczyk.pl> |
||||
*/ |
||||
class DumbMutex extends Mutex |
||||
{ |
||||
use RetryAcquireTrait; |
||||
|
||||
public $attemptsCounter = 0; |
||||
public static $locked = false; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function acquireLock($name, $timeout = 0) |
||||
{ |
||||
return $this->retryAcquire($timeout, function () { |
||||
$this->attemptsCounter++; |
||||
if (!static::$locked) { |
||||
static::$locked = true; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function releaseLock($name) |
||||
{ |
||||
if (static::$locked) { |
||||
static::$locked = false; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
} |
Loading…
Reference in new issue