#code from http://loose-bits.com/2010/10/distributed-task-locking-in-celery.html

import redis

REDIS_CLIENT = redis.Redis()


def only_one(function=None, ikey="", timeout=None):
    """Enforce only one celery task at a time."""

    def _dec(run_func):
        """Decorator."""

        def _caller(*args, **kwargs):
            """Caller."""
            ret_value = None
            have_lock = False
            # for item in kwargs.iteritems():
            #     print item
            key = kwargs.pop('keytask', ikey)
            lock = REDIS_CLIENT.lock(key, timeout=timeout)
            try:
                have_lock = lock.acquire(blocking=False)
                if have_lock:
                    ret_value = run_func(*args, **kwargs)
            finally:
                if have_lock:
                    lock.release()

            return ret_value

        return _caller

    return _dec(function) if function is not None else _dec
