Пример #1
0
    def acquire(self):
        """
        Attempt to acquire the lock.

        If the lock is successfully acquired, this method returns a context
        manager that will automatically release the lock when exited. If the
        lock cannot be acquired, an ``UnableToAcquireLock`` error will be
        raised.
        """
        try:
            self.backend.acquire(self.key, self.duration, self.routing_key)
        except Exception as error:
            six.raise_from(
                UnableToAcquireLock(
                    u"Unable to acquire {!r} due to error: {}".format(
                        self, error)),
                error,
            )

        @contextmanager
        def releaser():
            try:
                yield
            finally:
                self.release()

        return releaser()
Пример #2
0
    def blocking_acquire(self,
                         initial_delay: float,
                         timeout: float,
                         exp_base=1.6):
        """
        Try to acquire the lock in a polling loop.

        :param initial_delay: A random retry delay will be picked between 0
            and this value (in seconds). The range from which we pick doubles
            in every iteration.
        :param timeout: Time in seconds after which ``UnableToAcquireLock``
            will be raised.
        """
        stop = time.monotonic() + timeout
        attempt = 0
        while time.monotonic() < stop:
            try:
                return self.acquire()
            except UnableToAcquireLock:
                delay = (exp_base**attempt) * random.random() * initial_delay
                # Redundant check to prevent futile sleep in last iteration:
                if time.monotonic() + delay > stop:
                    break

                time.sleep(delay)

            attempt += 1

        raise UnableToAcquireLock(
            f"Unable to acquire {self!r} because of timeout")