from flask import current_app
from functools import wraps
from hashlib import md5

from changes.ext.redis import UnableToGetLock
from changes.config import redis


def lock(func):
    @wraps(func)
    def wrapped(**kwargs):
        key = '{0}:{1}:{2}'.format(
            func.__module__,
            func.__name__,
            md5(
                '&'.join('{0}={1}'.format(k, repr(v))
                for k, v in sorted(kwargs.iteritems()))
            ).hexdigest()
        )
        try:
            with redis.lock(key, expire=300, nowait=True):
                return func(**kwargs)
        except UnableToGetLock:
            current_app.logger.warn('Unable to get lock for %s', key)

    return wrapped

from flask import current_app
from functools import wraps
from hashlib import md5

from changes.ext.redis import UnableToGetLock
from changes.config import redis


def lock(func):
    @wraps(func)
    def wrapped(**kwargs):
        key = '{0}:{1}:{2}'.format(
            func.__module__,
            func.__name__,
            md5(
                '&'.join('{0}={1}'.format(k, repr(v))
                for k, v in sorted(kwargs.iteritems()))
            ).hexdigest()
        )
        try:
            with redis.lock(key, expire=300, nowait=True):
                return func(**kwargs)
        except UnableToGetLock:
            current_app.logger.warn('Unable to get lock for %s', key)
            raise

    return wrapped

Raise exception when we fail to grab a redis lock.
Raise exception when we fail to grab a redis lock.

Summary:
I might be missing something but it seems odd that we don't raise an error
when we fail to grab a lock and consequently not run the wrapped function.
We wrap all our tracked tasks with this lock function so failing to grab
the lock will appear as if the task finished successfully.

Reviewers: nate, josiah

Reviewed By: nate, josiah

Subscribers: changesbot, kylec

Differential Revision: https://tails.corp.dropbox.com/D192147
