Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#12: Add expiration time for memcache lock storage #13

Merged
merged 32 commits into from
Jun 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f6829d5
Add expire for Memcache and Memcached lock storage
arvenil Jun 11, 2015
3159f51
Let's try to test this
arvenil Jun 11, 2015
8be6e14
Better method to write this test; make the test run as @medium
arvenil Jun 11, 2015
22e5227
Hmm
arvenil Jun 11, 2015
f028cf0
Avoid interfering locks with each other by adding uuid to lock name
arvenil Jun 12, 2015
3ebd315
Bugfix, this reminds me why I love strict typing
arvenil Jun 12, 2015
8762483
Let's try to fix hhvm build
arvenil Jun 12, 2015
8391419
Yet another try to fix hhvm
arvenil Jun 12, 2015
9e02b64
Let's see what will happen if I will directly clear objects
arvenil Jun 12, 2015
8adb2fd
Let's try to fix php builds
arvenil Jun 12, 2015
a29e5d7
Let's try to catch and discard exceptions that are thrown while destr…
arvenil Jun 12, 2015
d1e87d9
Let's try this way
arvenil Jun 12, 2015
aa145d7
Ups
arvenil Jun 12, 2015
4a36c6b
WTH
arvenil Jun 12, 2015
0875db4
Let's try this trick
arvenil Jun 12, 2015
b6f3516
`--dev` param is obsolete in new composer
arvenil Jun 12, 2015
f7313aa
Ups, don't push dev code
arvenil Jun 12, 2015
0157c7e
Try to make tests run for php 5.3
arvenil Jun 12, 2015
faaba39
Let's check if now maybe exceptions are properly raised
arvenil Jun 12, 2015
4a90354
That php 5.3:/
arvenil Jun 12, 2015
8c9a77f
Let's see what happens
arvenil Jun 12, 2015
dc7a6c1
Bugfix, bad copy & paste
arvenil Jun 12, 2015
d9517d3
bugfix: invalid provider
arvenil Jun 12, 2015
7fda3f7
Let's try to be compatibile with travis version
arvenil Jun 12, 2015
97d4b56
No idea what's still not compatibile
arvenil Jun 12, 2015
4d474f9
Let's try to trick this broken memcached extension
arvenil Jun 12, 2015
d85075a
Implement proper interfaces
arvenil Jun 12, 2015
f42fccb
It's not chainable
arvenil Jun 12, 2015
5bd91ec
Let's finally try to expect Fatal Error
arvenil Jun 12, 2015
030f32b
Test alternative approach
arvenil Jun 12, 2015
3f0b3c5
Let's try this
arvenil Jun 12, 2015
d4f516f
Looks like we need separate method
arvenil Jun 12, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .travis.php.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
extension=memcache.so
extension=memcached.so
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ services:
- redis-server

before_script:
- ./tests/travis/memcache-setup.sh
- ./tests/travis/memcached-setup.sh
- if [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then cat .travis.php.ini >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; echo "Loading additional config for version $TRAVIS_PHP_VERSION" ; fi
- ./tests/travis/composer-setup.sh
- ./tests/travis/mysql-setup.sh

Expand Down
29 changes: 29 additions & 0 deletions src/NinjaMutex/Lock/LockExpirationInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
/**
* This file is part of ninja-mutex.
*
* (C) Kamil Dziedzic <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace NinjaMutex\Lock;

/**
* Lock implementor
*
* @author Kamil Dziedzic <[email protected]>
*/
interface LockExpirationInterface
{
/**
* @param int $expiration Expiration time of the lock in seconds.
*/
public function setExpiration($expiration);

/**
* @param string $name
* @return bool
*/
public function clearLock($name);
}
98 changes: 96 additions & 2 deletions src/NinjaMutex/Lock/MemcacheLock.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,107 @@
*
* @author Kamil Dziedzic <[email protected]>
*/
class MemcacheLock extends MemcacheLockAbstract
class MemcacheLock extends LockAbstract implements LockExpirationInterface
{
/**
* Maximum expiration time in seconds (30 days)
* http://php.net/manual/en/memcache.add.php
*/
const MAX_EXPIRATION = 2592000;

/**
* Memcache connection
*
* @var Memcache
*/
protected $memcache;

/**
* @var int Expiration time of the lock in seconds
*/
protected $expiration = 0;

/**
* @param Memcache $memcache
*/
public function __construct(Memcache $memcache)
{
parent::__construct($memcache);
parent::__construct();

$this->memcache = $memcache;
}

/**
* @param int $expiration Expiration time of the lock in seconds. If it's equal to zero (default), the lock will never expire.
* Max 2592000s (30 days), if greater it will be capped to 2592000 without throwing an error.
* WARNING: Using value higher than 0 may lead to race conditions. If you set too low expiration time
* e.g. 30s and critical section will run for 31s another process will gain lock at the same time,
* leading to unpredicted behaviour. Use with caution.
*/
public function setExpiration($expiration)
{
if ($expiration > static::MAX_EXPIRATION) {
$expiration = static::MAX_EXPIRATION;
}
$this->expiration = $expiration;
}

/**
* Clear lock without releasing it
* Do not use this method unless you know what you do
*
* @param string $name name of lock
* @return bool
*/
public function clearLock($name)
{
if (!isset($this->locks[$name])) {
return false;
}

unset($this->locks[$name]);
return true;
}

/**
* @param string $name name of lock
* @param bool $blocking
* @return bool
*/
protected function getLock($name, $blocking)
{
if (!$this->memcache->add($name, serialize($this->getLockInformation()), 0, $this->expiration)) {
return false;
}

return true;
}

/**
* Release lock
*
* @param string $name name of lock
* @return bool
*/
public function releaseLock($name)
{
if (isset($this->locks[$name]) && $this->memcache->delete($name)) {
unset($this->locks[$name]);

return true;
}

return false;
}

/**
* Check if lock is locked
*
* @param string $name name of lock
* @return bool
*/
public function isLocked($name)
{
return false !== $this->memcache->get($name);
}
}
77 changes: 0 additions & 77 deletions src/NinjaMutex/Lock/MemcacheLockAbstract.php

This file was deleted.

101 changes: 98 additions & 3 deletions src/NinjaMutex/Lock/MemcachedLock.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,108 @@
*
* @author Kamil Dziedzic <[email protected]>
*/
class MemcachedLock extends MemcacheLockAbstract
class MemcachedLock extends LockAbstract implements LockExpirationInterface
{
/**
* Maximum expiration time in seconds (30 days)
* http://php.net/manual/en/memcached.add.php
*/
const MAX_EXPIRATION = 2592000;

/**
* Memcache connection
*
* @var Memcached
*/
protected $memcached;

/**
* @var int Expiration time of the lock in seconds
*/
protected $expiration = 0;

/**
* @param Memcached $memcached
*/
public function __construct(Memcached $memcached)
public function __construct($memcached)
{
parent::__construct();

$this->memcached = $memcached;
}

/**
* @param int $expiration Expiration time of the lock in seconds. If it's equal to zero (default), the lock will never expire.
* Max 2592000s (30 days), if greater it will be capped to 2592000 without throwing an error.
* WARNING: Using value higher than 0 may lead to race conditions. If you set too low expiration time
* e.g. 30s and critical section will run for 31s another process will gain lock at the same time,
* leading to unpredicted behaviour. Use with caution.
*/
public function setExpiration($expiration)
{
if ($expiration > static::MAX_EXPIRATION) {
$expiration = static::MAX_EXPIRATION;
}
$this->expiration = $expiration;
}

/**
* Clear lock without releasing it
* Do not use this method unless you know what you do
*
* @param string $name name of lock
* @return bool
*/
public function clearLock($name)
{
parent::__construct($memcached);
if (!isset($this->locks[$name])) {
return false;
}

unset($this->locks[$name]);
return true;
}

/**
* @param string $name name of lock
* @param bool $blocking
* @return bool
*/
protected function getLock($name, $blocking)
{
if (!$this->memcached->add($name, serialize($this->getLockInformation()), $this->expiration)) {
return false;
}

return true;
}

/**
* Release lock
*
* @param string $name name of lock
* @return bool
*/
public function releaseLock($name)
{
if (isset($this->locks[$name]) && $this->memcached->delete($name)) {
unset($this->locks[$name]);

return true;
}

return false;
}

/**
* Check if lock is locked
*
* @param string $name name of lock
* @return bool
*/
public function isLocked($name)
{
return false !== $this->memcached->get($name);
}
}

Loading