Receive a raw BSON message or raise socket.error.
(
conn: AsyncConnection,
request_id: Optional[int],
max_message_size: int = MAX_MESSAGE_SIZE,
)
| 693 | |
| 694 | |
| 695 | async def async_receive_message( |
| 696 | conn: AsyncConnection, |
| 697 | request_id: Optional[int], |
| 698 | max_message_size: int = MAX_MESSAGE_SIZE, |
| 699 | ) -> Union[_OpReply, _OpMsg]: |
| 700 | """Receive a raw BSON message or raise socket.error.""" |
| 701 | timeout: Optional[Union[float, int]] |
| 702 | timeout = conn.conn.gettimeout |
| 703 | if _csot.get_timeout(): |
| 704 | deadline = _csot.get_deadline() |
| 705 | else: |
| 706 | if timeout: |
| 707 | deadline = time.monotonic() + timeout |
| 708 | else: |
| 709 | deadline = None |
| 710 | if deadline: |
| 711 | # When the timeout has expired perform one final check to |
| 712 | # see if the socket is readable. This helps avoid spurious |
| 713 | # timeouts on AWS Lambda and other FaaS environments. |
| 714 | timeout = max(deadline - time.monotonic(), 0) |
| 715 | |
| 716 | cancellation_task = create_task(_poll_cancellation(conn)) |
| 717 | read_task = create_task(conn.conn.get_conn.read(request_id, max_message_size)) |
| 718 | tasks = [read_task, cancellation_task] |
| 719 | try: |
| 720 | done, pending = await asyncio.wait( |
| 721 | tasks, timeout=timeout, return_when=asyncio.FIRST_COMPLETED |
| 722 | ) |
| 723 | for task in pending: |
| 724 | task.cancel() |
| 725 | if pending: |
| 726 | await asyncio.wait(pending) |
| 727 | if len(done) == 0: |
| 728 | raise socket.timeout("timed out") |
| 729 | if read_task in done: |
| 730 | data, op_code = read_task.result() |
| 731 | try: |
| 732 | unpack_reply = _UNPACK_REPLY[op_code] |
| 733 | except KeyError: |
| 734 | raise ProtocolError( |
| 735 | f"Got opcode {op_code!r} but expected {_UNPACK_REPLY.keys()!r}" |
| 736 | ) from None |
| 737 | return unpack_reply(data) |
| 738 | raise _OperationCancelled("operation cancelled") |
| 739 | except asyncio.CancelledError: |
| 740 | for task in tasks: |
| 741 | task.cancel() |
| 742 | await asyncio.wait(tasks) |
| 743 | raise |
| 744 | |
| 745 | |
| 746 | def receive_message( |
no test coverage detected