|
8 | 8 | import threading |
9 | 9 | import uuid |
10 | 10 | from itertools import count |
| 11 | +import queue as sync_queue |
11 | 12 | from typing import Callable, Awaitable |
12 | 13 |
|
13 | 14 | import certifi |
@@ -231,7 +232,7 @@ async def _callback(msg): |
231 | 232 | self._is_connected.clear() |
232 | 233 | if self._connection: |
233 | 234 | with contextlib.suppress(Exception): |
234 | | - await self._connection.close() # TODO: add code and reason |
| 235 | + await self._connection.close() |
235 | 236 | self._connection = None |
236 | 237 |
|
237 | 238 | self._is_running.clear() |
@@ -586,7 +587,7 @@ def wait(self, timeout=None) -> bool: |
586 | 587 | timeout (float): Timeout in seconds. |
587 | 588 |
|
588 | 589 | Returns: |
589 | | - True if the listener has stopped (before timeout), False otherwise. |
| 590 | + Whether the listener has stopped (before timeout). |
590 | 591 | """ |
591 | 592 | self._thread.join(timeout=timeout) |
592 | 593 | return not self._thread.is_alive() |
@@ -621,3 +622,101 @@ def ack(self, msg_id: str = None, payload: str = None) -> None: |
621 | 622 | """ |
622 | 623 | # assuming that we are already listening ... |
623 | 624 | asyncio.run_coroutine_threadsafe(self._listener.ack(msg_id, payload), self._event_loop) |
| 625 | + |
| 626 | + |
| 627 | +class AsyncQueueListener(object): |
| 628 | + """Special listener implementation which pushes notification messages |
| 629 | + into a standard (async) queue which can be monitored and read.""" |
| 630 | + |
| 631 | + def __init__( |
| 632 | + self, |
| 633 | + c8y: CumulocityApi, |
| 634 | + subscription_name: str, |
| 635 | + subscriber_name: str = None, |
| 636 | + consumer_name: str = None, |
| 637 | + shared: bool = False, |
| 638 | + auto_unsubscribe: bool = True, |
| 639 | + queue: asyncio.Queue = None |
| 640 | + ): |
| 641 | + self.queue = queue or asyncio.Queue() |
| 642 | + self.listener = AsyncListener( |
| 643 | + c8y=c8y, |
| 644 | + subscription_name=subscription_name, |
| 645 | + subscriber_name=subscriber_name, |
| 646 | + consumer_name=consumer_name, |
| 647 | + shared=shared, |
| 648 | + auto_ack=True, |
| 649 | + auto_unsubscribe=auto_unsubscribe, |
| 650 | + ) |
| 651 | + |
| 652 | + def start(self): |
| 653 | + """Start the listener.""" |
| 654 | + async def push_message(msg: AsyncListener.Message): |
| 655 | + self.queue.put_nowait(msg) |
| 656 | + |
| 657 | + self.listener.start(push_message) |
| 658 | + |
| 659 | + def stop(self): |
| 660 | + """Stop the listener.""" |
| 661 | + self.listener.stop() |
| 662 | + |
| 663 | + async def wait(self, timeout=None): |
| 664 | + """Wait for the listener task to finish. |
| 665 | +
|
| 666 | + Args: |
| 667 | + timeout (int): The number of seconds to wait for the listener |
| 668 | + to finish. The listener will be cancelled if the timeout |
| 669 | + occurs. |
| 670 | + """ |
| 671 | + await self.listener.wait(timeout=timeout) |
| 672 | + |
| 673 | + |
| 674 | +class QueueListener(object): |
| 675 | + """Special listener implementation which pushes notification messages |
| 676 | + into a standard (sync) queue which can be monitored and read.""" |
| 677 | + |
| 678 | + def __init__( |
| 679 | + self, |
| 680 | + c8y: CumulocityApi, |
| 681 | + subscription_name: str, |
| 682 | + subscriber_name: str = None, |
| 683 | + consumer_name: str = None, |
| 684 | + shared: bool = False, |
| 685 | + auto_unsubscribe: bool = True, |
| 686 | + queue: sync_queue.Queue = None |
| 687 | + ): |
| 688 | + self.queue = queue or sync_queue.Queue() |
| 689 | + self.listener = Listener( |
| 690 | + c8y=c8y, |
| 691 | + subscription_name=subscription_name, |
| 692 | + subscriber_name=subscriber_name, |
| 693 | + consumer_name=consumer_name, |
| 694 | + shared=shared, |
| 695 | + auto_ack=True, |
| 696 | + auto_unsubscribe=auto_unsubscribe, |
| 697 | + ) |
| 698 | + |
| 699 | + def start(self): |
| 700 | + """Start the listener.""" |
| 701 | + |
| 702 | + def push_message(msg: AsyncListener.Message): |
| 703 | + self.queue.put(msg) |
| 704 | + |
| 705 | + self.listener.start(push_message) |
| 706 | + |
| 707 | + def stop(self): |
| 708 | + """Stop the listener.""" |
| 709 | + self.listener.stop() |
| 710 | + |
| 711 | + def wait(self, timeout=None) -> bool: |
| 712 | + """Wait for the listener task to finish. |
| 713 | +
|
| 714 | + Args: |
| 715 | + timeout (int): The number of seconds to wait for the listener |
| 716 | + to finish. The listener will be cancelled if the timeout |
| 717 | + occurs. |
| 718 | +
|
| 719 | + Returns: |
| 720 | + Whether the listener has stopped (before timeout). |
| 721 | + """ |
| 722 | + return self.listener.wait(timeout=timeout) |
0 commit comments