Esempio n. 1
0
def acquire_lock(name, expiry=None, context=None, conn=None):
    """
    Acquire a lock in redis.

    :param str name: Name of the lock to acquire
    :param int expiry: The duration of the lock (in seconds)
    :param str context: The context to apply to the lock name
    :param redis.Connection conn: The redis connection to use
    :rtype: :class:`bool`
    :returns: Whether or not the lock was acquired
    """

    # pylint: disable=W0212
    current = time()
    lock_expiry = 3 if expiry is None else expiry
    lock_expires = current + lock_expiry
    lock_context = 'global.lock' if context is None else context
    lock_name = '%s:%s' % (lock_context, name)
    redis = get_redis_connection() if conn is None else conn

    # try to get lock; if we fail, do sanity check on lock
    if not redis.setnx(lock_name, lock_expires):
        # see if current lock is expired; if so, take it
        if current < float(redis.get(lock_name)):
            # lock is not expired
            return False
        elif current < float(redis.getset(lock_name, lock_expires)):
            # somebody else beat us to it
            return False

    # we have the lock; give it a TTL and pass through
    redis.expire(lock_name, lock_expiry)

    return True
Esempio n. 2
0
    def __init__(self, uuid=None):
        """
        Initialize the Actor object.

        :param str uuid: Optionally-provided UUID
        """

        atexit.register(self.__del__)
        self._stop = Event()
        #: Separate Thread for handling messages
        self._proc = None
        #: Redis connection
        self._redis = get_redis_connection()
        # pylint: disable=E1123
        self._pubsub = self._redis.pubsub(ignore_subscribe_messages=True)

        if uuid:
            self.uuid = uuid
        else:
            self.uuid = str(uuid4())

        if not REGISTRY.exists(self.uuid):
            REGISTRY.register(self.uuid)
        else:
            self.uuid = None
            raise UUIDInUseException('UUID is already taken')
Esempio n. 3
0
    def __init__(self, channel):
        """
        Initialize instance of ClusterProxy.

        :param str channel: The cluster channel to use
        """

        #: Cluster channel
        self.channel = channel
        #: Redis connection
        self._redis = get_redis_connection()
        #: Redis PubSub client
        self._pubsub = None
        #: This proxy object's UUID for creating unique channels
        self.proxyid = str(uuid4())
        #: Response queues for sandboxing method calls
        self._response_queues = {}
        #: Response counters for the response queue
        self._response_counters = {}
        self._stop = Event()
        # pylint: disable=E1123
        self._pubsub = self._redis.pubsub(ignore_subscribe_messages=True)
        self._pubsub.subscribe(**{'proxy:%s' % self.proxyid: self._handler})

        def pubsub_thread():
            """ Call get_message in loop to fire _handler. """

            try:
                while not self._stop.is_set():
                    self._pubsub.get_message()
                    sleep(0.001)
            except:  # pylint: disable=W0702
                pass

        # fire up the message handler thread as a daemon
        proc = Thread(target=pubsub_thread)
        proc.daemon = True
        proc.start()
Esempio n. 4
0
    def __init__(self, actor=None, uuid=None):
        """
        Initialize instance of ActorProxy.

        Accepts either an Actor object to clone or a UUID, but not both.

        :param rodario.actors.Actor actor: Actor to clone
        :param str uuid: UUID of Actor to clone
        """

        #: Redis connection
        self._redis = get_redis_connection()
        #: Redis PubSub client
        self._pubsub = None
        #: This proxy object's UUID for creating unique channels
        self.proxyid = str(uuid4())
        #: Response queues for sandboxing method calls
        self._response_queues = {}
        # avoid cyclic import
        actor_module = __import__('rodario.actors', fromlist=('Actor',))
        # pylint: disable=E1123
        self._pubsub = self._redis.pubsub(ignore_subscribe_messages=True)
        self._pubsub.subscribe(**{'proxy:%s' % self.proxyid: self._handler})

        methods = set()

        def pubsub_thread():
            """ Call get_message in loop to fire _handler. """

            try:
                while self._pubsub:
                    self._pubsub.get_message()
                    sleep(0.001)
            except:  # pylint: disable=W0702
                pass

        # fire up the message handler thread as a daemon
        proc = Thread(target=pubsub_thread)
        proc.daemon = True
        proc.start()

        if isinstance(actor, actor_module.Actor):
            # proxying an Actor directly
            self.uuid = actor.uuid
            methods = actor._get_methods()  # pylint: disable=W0212
        elif isinstance(uuid, str):
            # proxying by UUID; get actor methods over pubsub
            self.uuid = uuid
            methods = self._proxy('_get_methods').get()
        else:
            raise InvalidProxyException('No actor or UUID provided')

        def get_lambda(name):
            """
            Generate a lambda function to proxy the given method.

            :param str name: Name of the method to proxy
            :rtype: :expression:`lambda`
            """

            return lambda _, *args, **kwargs: self._proxy(name, *args, **kwargs)

        # create proxy methods for each public method of the original Actor
        for name in methods:
            setattr(self, name, types.MethodType(get_lambda(name), self))