Пример #1
0
async def test_nested_move_on_after():
    sleep_completed = inner_scope_completed = False
    async with move_on_after(0.1) as outer_scope:
        assert await current_effective_deadline() == outer_scope.deadline
        async with move_on_after(1) as inner_scope:
            assert await current_effective_deadline() == outer_scope.deadline
            await sleep(2)
            sleep_completed = True

        inner_scope_completed = True

    assert not sleep_completed
    assert not inner_scope_completed
    assert outer_scope.cancel_called
    assert not inner_scope.cancel_called
Пример #2
0
    async def acquire_jobs(self,
                           worker_id: str,
                           limit: Optional[int] = None) -> List[Job]:
        while True:
            jobs: List[Job] = []
            async with self.pool.acquire() as conn, conn.transaction():
                now = datetime.now(timezone.utc)
                acquired_until = datetime.fromtimestamp(
                    now.timestamp() + self.lock_expiration_delay, timezone.utc)
                records = await conn.fetch(
                    f"""
                    WITH job_ids AS (
                        SELECT id FROM {self.schema}.jobs
                        WHERE acquired_until IS NULL OR acquired_until < $1
                        ORDER BY created_at
                        FOR NO KEY UPDATE SKIP LOCKED
                        FETCH FIRST $2 ROWS ONLY
                    )
                    UPDATE {self.schema}.jobs SET acquired_by = $3, acquired_until = $4
                    WHERE id IN (SELECT id FROM job_ids)
                    RETURNING serialized_data
                    """, now, limit, worker_id, acquired_until)

            for record in records:
                job = self.serializer.deserialize(record['serialized_data'])
                jobs.append(job)

            if jobs:
                return jobs

            async with move_on_after(self.max_poll_time):
                await self._jobs_event.wait()
                self._jobs_event.clear()
Пример #3
0
    async def acquire_schedules(self, scheduler_id: str,
                                limit: int) -> List[Schedule]:
        while True:
            schedules: List[Schedule] = []
            async with self.pool.acquire() as conn, conn.transaction():
                acquired_until = datetime.fromtimestamp(
                    datetime.now(timezone.utc).timestamp() +
                    self.lock_expiration_delay, timezone.utc)
                records = await conn.fetch(
                    f"""
                    WITH schedule_ids AS (
                        SELECT id FROM {self.schema}.schedules
                        WHERE next_fire_time IS NOT NULL AND next_fire_time <= $1
                            AND (acquired_until IS NULL OR $1 > acquired_until)
                        ORDER BY next_fire_time
                        FOR NO KEY UPDATE SKIP LOCKED
                        FETCH FIRST $2 ROWS ONLY
                    )
                    UPDATE {self.schema}.schedules SET acquired_by = $3, acquired_until = $4
                    WHERE id IN (SELECT id FROM schedule_ids)
                    RETURNING serialized_data
                    """, datetime.now(timezone.utc), limit, scheduler_id,
                    acquired_until)

            for record in records:
                schedule = self.serializer.deserialize(
                    record['serialized_data'])
                schedules.append(schedule)

            if schedules:
                return schedules

            async with move_on_after(self.max_poll_time):
                await self._schedules_event.wait()
Пример #4
0
    async def debouncer(self, chan, q):
        while True:
            e1 = await q.get()
            logger.debug("new %s %s", self.name, e1)
            val = not self.value
            # something happens. Send an event immediately,
            # no matter the event's value.
            await self.handle_event(val, chan)

            e2 = None
            while True:
                async with anyio.move_on_after(abs(self.debounce)) as skip:
                    e2 = await q.get()
                    logger.debug("and %s %s", self.name, e2)
                if skip.cancel_called:
                    break

            logger.debug("done %s %s", self.name, e2)
            if self.debounce < 0:
                if e2 is None or e1.value == e2.value:
                    await self.handle_event(e1, chan)
            else:
                await self.handle_event(e1, chan)
                if e2 is not None and e1.value != e2.value:
                    await self.handle_event(e2, chan)
Пример #5
0
    async def multi_sleep(self, durations: List[float], timeout: float) -> bool:
        async with anyio.move_on_after(timeout) as cancel_scope:
            async with anyio.create_task_group() as task_group:
                for duration in durations:
                    await task_group.spawn(self.sleep, duration)

        return not cancel_scope.cancel_called
Пример #6
0
 async def __aexit__(self, *tb):
     self._q = None
     try:
         async with anyio.move_on_after(2, shield=True):
             await self.client._unsubscribe(self)
     except ClientException:
         pass
Пример #7
0
async def test_streaming_response_stops_if_receiving_http_disconnect():
    streamed = 0

    disconnected = anyio.Event()

    async def receive_disconnect():
        await disconnected.wait()
        return {"type": "http.disconnect"}

    async def send(message):
        nonlocal streamed
        if message["type"] == "http.response.body":
            streamed += len(message.get("body", b""))
            # Simulate disconnection after download has started
            if streamed >= 16:
                disconnected.set()

    async def stream_indefinitely():
        while True:
            # Need a sleep for the event loop to switch to another task
            await anyio.sleep(0)
            yield b"chunk "

    response = StreamingResponse(content=stream_indefinitely())

    with anyio.move_on_after(1) as cancel_scope:
        await response({}, receive_disconnect, send)
    assert not cancel_scope.cancel_called, "Content streaming should stop itself."
Пример #8
0
    async def _next_to_send(self):
        """
        Returns the next message on the heap
        """
        while True:
            while self._heap:
                if self._heap_large is not None and len(
                        self._heap) < self._heap_max / 2:
                    await self._heap_large.set()
                    self._heap_large = None

                if self._ending.is_set(
                ) or self._heap[0].time <= self._t - self._delay:
                    return heapq.heappop(self._heap)
                self._t = time.time()
                if self._heap[0].time <= self._t - self._delay:
                    return heapq.heappop(self._heap)
                async with anyio.move_on_after(
                        max(self._delay + self._heap[0].time - self._t, 0)):
                    await self._ending.wait()

            await self.flush_buf()
            if self._done is not None:
                await self._done.set()
            self._heap_item = anyio.create_event()
            await self._heap_item.wait()
Пример #9
0
async def test_acquire_schedules_lock_timeout(store, schedules, events,
                                              freezer):
    """
    Test that a scheduler can acquire schedules that were acquired by another scheduler but not
    released within the lock timeout period.

    """
    # First, one scheduler acquires the first available schedule
    await store.add_schedule(schedules[0], ConflictPolicy.exception)
    acquired = await store.acquire_schedules('dummy-id1', 1)
    assert len(acquired) == 1
    assert acquired[0].id == 's1'

    # Try to acquire the schedule just at the threshold (now == acquired_until).
    # This should not yield any schedules.
    freezer.tick(30)
    async with move_on_after(0.2):
        await store.acquire_schedules('dummy-id2', 1)
        pytest.fail('The call should have timed out')

    # Right after that, the schedule should be available
    freezer.tick(1)
    acquired = await store.acquire_schedules('dummy-id2', 1)
    assert len(acquired) == 1
    assert acquired[0].id == 's1'
Пример #10
0
    async def teardown(self, hangup_reason="normal"):
        """Removes all channels from the bridge and destroys it.

        All remaining channels are hung up.

        This method is typically called when leaving the bridge's context
        manager. If you want to keep it online, e.g. for being able to
        cleanly restart a PBX without downtime, you may override this --
        but you're then responsible for recovering state after restarting,
        and you still need to clean up bridges that are no longer needed.

        """
        if self.bridge is None:
            return
        async with anyio.move_on_after(2, shield=True) as s:
            log.info("TEARDOWN %s %s", self, self.bridge.channels)
            for ch in list(self.bridge.channels) + list(self.calls):
                try:
                    await ch.hang_up(reason=hangup_reason)
                except Exception as exc:
                    log.info("%s gone: %s", ch, exc)

                try:
                    await self.bridge.removeChannel(channel=ch.id)
                except Exception as exc:
                    log.info("%s detached: %s", ch, exc)

            await self.bridge.destroy()
Пример #11
0
    async def self_cancel(*, task_status: TaskStatus) -> None:
        nonlocal done
        task_status.started()
        with move_on_after(-1):
            await Event().wait()

        done = True
Пример #12
0
    async def acquire_schedules(self, scheduler_id: str, limit: int) -> List[Schedule]:
        while True:
            schedules: List[Schedule] = []
            async with await self.client.start_session() as s, s.start_transaction():
                cursor = self._schedules.find(
                    {'next_fire_time': {'$ne': None},
                     '$or': [{'acquired_until': {'$exists': False}},
                             {'acquired_until': {'$lt': datetime.now(timezone.utc)}}]
                     },
                    projection=['serialized_data']
                ).sort('next_fire_time')
                for document in await cursor.to_list(length=limit):
                    schedule = self.serializer.deserialize(document['serialized_data'])
                    schedules.append(schedule)

                if schedules:
                    now = datetime.now(timezone.utc)
                    acquired_until = datetime.fromtimestamp(
                        now.timestamp() + self.lock_expiration_delay, now.tzinfo)
                    filters = {'_id': {'$in': [schedule.id for schedule in schedules]}}
                    update = {'$set': {'acquired_by': scheduler_id,
                                       'acquired_until': acquired_until}}
                    await self._schedules.update_many(filters, update)
                    return schedules

            async with move_on_after(self.max_poll_time):
                await self._schedules_event.wait()
Пример #13
0
    async def _sender_loop(self, evt):
        keepalive_timeout = self.session.keep_alive
        if keepalive_timeout <= 0:
            keepalive_timeout = None

        try:
            async with anyio.open_cancel_scope() as scope:
                self._sender_task = scope
                await evt.set()
                while True:
                    packet = None
                    async with anyio.move_on_after(keepalive_timeout):
                        packet = await self._send_q.get()
                        if packet is None:  # closing
                            break
                    if packet is None:  # timeout
                        await self.handle_write_timeout()
                        continue
                    # self.logger.debug("%s > %r",'B' if 'Broker' in type(self).__name__ else 'C', packet)
                    await packet.to_stream(self.stream)
                    await self.plugins_manager.fire_event(
                        EVENT_MQTT_PACKET_SENT,
                        packet=packet,
                        session=self.session)
        except ConnectionResetError:
            await self.handle_connection_closed()
        except anyio.get_cancelled_exc_class():
            raise
        except BaseException as e:
            self.logger.warning("Unhandled exception", exc_info=e)
            raise
        finally:
            async with anyio.fail_after(2, shield=True):
                await self._sender_stopped.set()
            self._sender_task = None
Пример #14
0
    async def acquire_schedules(self, scheduler_id: str,
                                limit: int) -> List[Schedule]:
        while True:
            now = datetime.now(timezone.utc)
            schedules: List[Schedule] = []
            wait_time = None
            for state in self._schedules:
                if state.acquired_by is not None and state.acquired_until >= now:
                    continue
                elif state.next_fire_time is None:
                    break
                elif state.next_fire_time > now:
                    wait_time = state.next_fire_time.timestamp(
                    ) - now.timestamp()
                    break

                schedules.append(state.schedule)
                state.acquired_by = scheduler_id
                state.acquired_until = datetime.fromtimestamp(
                    now.timestamp() + self.lock_expiration_delay, now.tzinfo)
                if len(schedules) == limit:
                    break

            if schedules:
                return schedules

            # Wait until reaching the next known fire time, or a schedule is added or updated
            async with move_on_after(wait_time):
                await self._schedules_event.wait()
Пример #15
0
async def test_acquire_release_jobs(store, jobs, events):
    for job in jobs:
        await store.add_job(job)

    events.clear()

    # The first worker gets the first job in the queue
    jobs1 = await store.acquire_jobs('dummy-id1', 1)
    assert len(jobs1) == 1
    assert jobs1[0].id == jobs[0].id

    # The second worker gets the second job
    jobs2 = await store.acquire_jobs('dummy-id2', 1)
    assert len(jobs2) == 1
    assert jobs2[0].id == jobs[1].id

    # The third worker gets nothing
    async with move_on_after(0.2):
        await store.acquire_jobs('dummy-id3', 1)
        pytest.fail('The call should have timed out')

    # All the jobs should still be returned
    visible_jobs = await store.get_jobs()
    assert len(visible_jobs) == 2

    await store.release_jobs('dummy-id1', jobs1)
    await store.release_jobs('dummy-id2', jobs2)

    # All the jobs should be gone
    visible_jobs = await store.get_jobs()
    assert len(visible_jobs) == 0
Пример #16
0
async def test_escaping_cancelled_error_from_cancelled_task():
    """Regression test for issue #88. No CancelledError should escape the outer scope."""
    async with open_cancel_scope() as scope:
        async with move_on_after(0.1):
            await sleep(1)

        await scope.cancel()
Пример #17
0
    async def mqtt_publish(self, topic, data, qos, retain, ack_timeout=None):
        """
        Sends a MQTT publish message and manages messages flows.
        This methods doesn't return until the message has been acknowledged by receiver or timeout occur
        :param topic: MQTT topic to publish
        :param data:  data to send on topic
        :param qos: quality of service to use for message flow. Can be QOS_0, QOS_1 or QOS_2
        :param retain: retain message flag
        :param ack_timeout: acknowledge timeout. If set, this method will return a TimeOut error if the acknowledgment
        is not completed before ack_timeout second
        :return: ApplicationMessage used during inflight operations
        """
        if qos in (QOS_1, QOS_2):
            packet_id = self.session.next_packet_id
            if packet_id in self.session.inflight_out:
                raise HBMQTTException(
                    "A message with the same packet ID '%d' is already in flight"
                    % packet_id)
        else:
            packet_id = None

        message = OutgoingApplicationMessage(packet_id, topic, qos, data,
                                             retain)
        # Handle message flow
        if ack_timeout is not None and ack_timeout > 0:
            async with anyio.move_on_after(ack_timeout):
                await self._handle_message_flow(message)
        else:
            await self._handle_message_flow(message)

        return message
Пример #18
0
    async def acquire_jobs(self, worker_id: str, limit: Optional[int] = None) -> List[Job]:
        jobs: List[Job] = []
        while True:
            async with await self.client.start_session() as s, s.start_transaction():
                cursor = self._jobs.find(
                    {'$or': [{'acquired_until': {'$exists': False}},
                             {'acquired_until': {'$lt': datetime.now(timezone.utc)}}]
                     },
                    projection=['serialized_data'],
                    sort=[('created_at', ASCENDING)]
                )
                for document in await cursor.to_list(length=limit):
                    job = self.serializer.deserialize(document['serialized_data'])
                    jobs.append(job)

                if jobs:
                    now = datetime.now(timezone.utc)
                    acquired_until = datetime.fromtimestamp(
                        now.timestamp() + self.lock_expiration_delay, timezone.utc)
                    filters = {'_id': {'$in': [job.id for job in jobs]}}
                    update = {'$set': {'acquired_by': worker_id,
                                       'acquired_until': acquired_until}}
                    await self._jobs.update_many(filters, update)
                    return jobs

            async with move_on_after(self.max_poll_time):
                await self._jobs_event.wait()
                self._jobs_event.clear()
Пример #19
0
async def test_escaping_cancelled_error_from_cancelled_task() -> None:
    """Regression test for issue #88. No CancelledError should escape the outer scope."""
    with CancelScope() as scope:
        with move_on_after(0.1):
            await sleep(1)

        scope.cancel()
Пример #20
0
 async def _handle_disconnect(self, disconnect, wait=True):  # pylint: disable=arguments-differ
     self.logger.debug("Client disconnecting")
     self.clean_disconnect = False  # depending on 'disconnect' (if set)
     async with anyio.fail_after(2, shield=True):
         if wait:
             async with anyio.move_on_after(self.session.keep_alive):
                 await self._reader_stopped.wait()
         await self.stop()
Пример #21
0
 async def _handle_disconnect(self, disconnect, wait=True):
     self.logger.debug("Client disconnecting")
     self.clean_disconnect = False  # depending on 'disconnect' (if set)
     async with anyio.open_cancel_scope(shield=True):
         if wait:
             async with anyio.move_on_after(self.session.keep_alive):
                 await self._reader_stopped.wait()
         await self.stop()
Пример #22
0
async def test_move_on_after(delay: float) -> None:
    result = False
    with move_on_after(delay) as scope:
        await sleep(1)
        result = True

    assert not result
    assert scope.cancel_called
Пример #23
0
    async def test_should_work_when_using_task_done_and_join_methods(self):
        async with Queue(size=1) as queue:
            await queue.put(2)
            await queue.get()
            assert 1 == queue._tasks_in_progress

            with anyio.move_on_after(1) as cancel_scope:
                await queue.join()

            assert cancel_scope.cancel_called
            queue.task_done()
            assert 0 == queue._tasks_in_progress

            with anyio.move_on_after(1) as cancel_scope:
                await queue.join()

            assert not cancel_scope.cancel_called
Пример #24
0
 async def __aexit__(self, *tb):
     if not self.channel.is_open:
         return
     async with anyio.move_on_after(2, shield=True):
         try:
             await self.channel.close()
         except exceptions.AmqpClosedConnection:
             pass
Пример #25
0
async def socketSend(ws):
    async with capture_continuous() as agen:
        with anyio.move_on_after(20):
            async for frame, msg in agen:
                print("sending message")
                await ws.send(msg)
                print("waiting for response")
                print(await ws.recv())
Пример #26
0
 async def serve(self) -> None:
     await self._master.register_service(self.service_name)
     try:
         await anyio.sleep_forever()
     except anyio.get_cancelled_exc_class():
         with anyio.CancelScope(shield=True), anyio.move_on_after(1):
             await self._master.unregister_service(self.service_name)
         raise
Пример #27
0
async def test_move_on_after():
    result = False
    async with move_on_after(0.1) as scope:
        await sleep(1)
        result = True

    assert not result
    assert scope.cancel_called
Пример #28
0
async def test_move_on_after_no_timeout():
    result = False
    async with move_on_after(None) as scope:
        assert scope.deadline == float('inf')
        await sleep(0.1)
        result = True

    assert result
    assert not scope.cancel_called
Пример #29
0
        async def process_one(message):
            async with anyio.move_on_after(10):
                try:
                    await self._handle_message_flow(message)
                except CancelledError:
                    pass

                nonlocal done
                done += 1
Пример #30
0
        async def process_one(message):
            async with anyio.move_on_after(10):
                try:
                    await self._handle_message_flow(message)
                except CancelledError:
                    pass

                nonlocal done
                done += 1  # pylint: disable=undefined-variable  ## fixed in 2.5