Giter VIP home page Giter VIP logo

mutex's Introduction

License PHP Version

Build

Coverage Quality Maintainability Grade Total Downloads

About

ninja-mutex is a simple to use mutex implementation for php. It supports different adapters (flock, memcache, mysql, redis, ...) so you can set it up as you wish. All adapters (if set up properly) can be used in multi server environment - in other words lock is shared between web servers.

Usage

Mutex

First you need to choose an adapter and setup it properly. For example if you choose flock implementation first you need to set up NFS filesystem and mount it on web servers. In this example we will choose memcache adapter:

<?php
require 'vendor/autoload.php';

use NinjaMutex\Lock\MemcacheLock;
use NinjaMutex\Mutex;

$memcache = new Memcache();
$memcache->connect('127.0.0.1', 11211);
$lock = new MemcacheLock($memcache);
$mutex = new Mutex('very-critical-stuff', $lock);
if ($mutex->acquireLock(1000)) {
    // Do some very critical stuff

    // and release lock after you finish
    $mutex->releaseLock();
} else {
    throw new Exception('Unable to gain lock!');
}

Mutex Fabric

If you want to use multiple mutexes in your project then MutexFabric is the right solution. Set up lock implementor once, and you can use as many mutexes as you want!

<?php
require 'vendor/autoload.php';

use NinjaMutex\Lock\MemcacheLock;
use NinjaMutex\MutexFabric;

$memcache = new Memcache();
$memcache->connect('127.0.0.1', 11211);
$lock = new MemcacheLock($memcache);
$mutexFabric = new MutexFabric('memcache', $lock);
if ($mutexFabric->get('very-critical-stuff')->acquireLock(1000)) {
    // Do some very critical stuff

    // and release lock after you finish
    $mutexFabric->get('very-critical-stuff')->releaseLock();
} else {
    throw new Exception('Unable to gain lock for very critical stuff!');
}

if ($mutexFabric->get('also-very-critical-stuff')->acquireLock(0)) {
    // Do some also very critical stuff

    // and release lock after you finish
    $mutexFabric->get('also-very-critical-stuff')->releaseLock();
} else {
    throw new Exception('Unable to gain lock for also very critical stuff!');
}

Installation

Composer

Download composer:

wget -nc http://getcomposer.org/composer.phar

Add dependency to your project:

php composer.phar require arvenil/ninja-mutex:*

Running tests

Tests require vfsStream to work. To install it, simply run in project dir:

wget -nc http://getcomposer.org/composer.phar && php composer.phar install --dev

To run tests type in a console:

vendor/bin/phpunit

Something doesn't work

Feel free to fork project, fix bugs and finally request for pull

mutex's People

Contributors

arvenil avatar benallfree avatar dcc34676 avatar dnna avatar janvoracek avatar leo108 avatar noisebynorthwest avatar seb147 avatar whatson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mutex's Issues

Mutex signals are not preventing concurrent duplicates

Hi. I'm trying ninja-mutex with redis. The execution infrastructure is AWS with elasticache.
Four cron docker containers acquire mutex signal in order to prevent duplicates (to work like in a queue). I mean: two instances cannot process the same object from db because they are creating mutexes with the object ids.

In local environment it works well emulating concurrency with tools like "parallel" from shell. But in AWS environment it is not working well concurrently... duplicate objects are created.

Am I missing something? may I to implement a more advanced locking mechanism like the one described by redis.io? (https://redis.io/topics/distlock)

Thanks in advance

possible to set memcache 'expire' on locks?

Hi, First of all thanks for the great library! Here I have some problems with un-released locks.

I am calling many 3rd party libraries between lock & release. Very occasionally I could get a fatal crash that the lock is never cleaned up.

My process typically takes 3~5 sec to complete, is it possible to set an expire value for the lock?
E.g. 60 sec, so it is not locked forever.

I could see the alternative maybe using flock so file system handles it...

My code is very simple like this:

$mutex = new Mutex('very-critical-stuff', $lock);
if ($mutex->acquireLock(1000)) {
    // calling many 3rd party libraries.
    // !!! Fatal error crash.
    // the lock is never released
    $mutex->releaseLock();
} else {
    throw new Exception('Unable to gain lock!');
}

FlockLock failed to remove temporary lock file.

Hello,

I'm using FlockLock and after usage i have a lot of .lock file in the working directory.
I tried to look for a cleanup function but i didn't found one, I'm guessing the .lock files should be automatically removed after usage.
I'm using lock like this:

$key = 'some_key';
$value = 'some_value';
$lock = new NinjaMutex\Lock\FlockLock("/tmp");
$mutex = new NinjaMutex\Mutex($key, $lock);
if ($mutex->acquireLock(1000)) {
$mutex->releaseLock();
unset($mutex);
}

After running the code i have "/tmp/some_key.lock" file remaining.
Did I do something wrong or is it a bug ?

I tried on 5.6.17-0+deb8u1 (Debian), 5.6.11-1ubuntu3.1 (Ubuntu) i have the same behaviour.

Thanks!

Expose lock information

I see you collect lock information in LockAbstract it would be nice if there was to publicly get that info. Even as simple as making getLockInfo public. Although, it doesn't look like MySQL supports that. Maybe it could always return an empty array? Or another interface, maybe LockInfoAwareInterface?

Exception in destructor

I got exceptions like this:

Uncaught exception 'NinjaMutex\UnrecoverableMutexException' with message 'Cannot release lock in Mutex __destruct(): <mutex name> 'in /path/to/vendor/arvenil/ninja-mutex/src/NinjaMutex/Mutex.php:100
Stack trace:
#0 [internal function]: NinjaMutex\Mutex->__destruct()
#1 {main}
  thrown in /path/to/vendor/arvenil/ninja-mutex/src/NinjaMutex/Mutex.php on line 100

My code tries to deal with the exception by using unset manually to trigger the destructor and catch exception that might occur:

$mutex = $mutexFabric->get("<mutex name>");

$lock = $mutex->acquireLock();
if (!$lock) {
    throw new Exception("lock could not be acquired");
}
try {
    // CRITICAL SECTION
    $mutex->releaseLock();
    try {
        unset($mutex);
    } catch (Exception $unsetE) { }
} catch (Exception $e) {
    $mutex->releaseLock();
    try {
        unset($mutex);
    } catch (Exception $unsetE) { }
    throw $e;
}

However this does not work because the fabric stores references to the mutex and therefor the unset has no effect.
Could you introduce a method that forces the destruction of the mutex and throws catchable exceptions? Do you have an explanation on the reason of the exception? I am using memcached as backend.

Any plans to release a new version?

Hi @arvenil,

Thank you for your efforts in creating and maintaining this package!

I use it in one of my packages (dmitry-ivanov/laravel-console-mutex) and was curious - are there any plans to release a new version at some point?

One of the changes I'm interested in is the MySQLPDOLock which was introduced after the 0.6.0 (which is the latest released version now).

Thanks!

Redis lock with setnx will lead to deadlocks

Hello,

We used to use the library in one of our applications and we always got deadlocks when under certain load.
Because of the nature of such problems, it was extraordinary difficult to find why this happens, we have changed our code multiple times and never suspected the problem is caused by an underlaying library.

In one of the debug sessions, using strace we could see the process is stuck doing a SETNX command. Reading about the command at https://redis.io/commands/setnx#design-pattern-locking-with-codesetnxcode says it should not be used for this purposes anymore. Digging further to see what piece of code uses this command, we ended up finding https://github.com/arvenil/mutex/blob/master/src/Lock/PredisRedisLock.php#L45

Maybe you should look into it and find a better alternative.
Best.

How can I achieve the same behavior than the MySQL GET_LOCK() command?

For this example, I'm using the Memcached backend, and a timeout value of 0.

With MySQL GET_LOCK(), if a PHP script terminates before releasing explicitely the lock (Fatal Error for example), it is released anyway. However, with your library, if a PHP script terminates before releasing the lock, it can never get it again, because Memcached don't delete the lock automatically.

Multiple connections MySQL Lock

I wanted to lock a specific record in a data storage which are identified by UUID. To acquire the lock we do it like the following pseudo code:

if ( ! $this->lock->acquireLock($UUID)) {
   //logic
}

However by doing so we create a PDO connection for each UUID we want to lock since the MySqlLock sets up PDO by itself and stores a connection based on the name used for acquiring the lock (the UUID in this use case)

Looking at the other lock adapters we always inject the connection instead, is the mysql different by intention or just something we need to implement differently?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.