Create a batched OP_MSG write for client-level bulk write.
(
command: Mapping[str, Any],
operations: list[tuple[str, Mapping[str, Any]]],
namespaces: list[str],
ack: bool,
opts: CodecOptions[Any],
ctx: _ClientBulkWriteContext,
buf: _BytesIO,
)
| 1039 | |
| 1040 | |
| 1041 | def _client_batched_op_msg_impl( |
| 1042 | command: Mapping[str, Any], |
| 1043 | operations: list[tuple[str, Mapping[str, Any]]], |
| 1044 | namespaces: list[str], |
| 1045 | ack: bool, |
| 1046 | opts: CodecOptions[Any], |
| 1047 | ctx: _ClientBulkWriteContext, |
| 1048 | buf: _BytesIO, |
| 1049 | ) -> tuple[list[Mapping[str, Any]], list[Mapping[str, Any]], int]: |
| 1050 | """Create a batched OP_MSG write for client-level bulk write.""" |
| 1051 | |
| 1052 | def _check_doc_size_limits( |
| 1053 | op_type: str, |
| 1054 | doc_size: int, |
| 1055 | limit: int, |
| 1056 | ) -> None: |
| 1057 | if doc_size > limit: |
| 1058 | _raise_document_too_large(op_type, doc_size, limit) |
| 1059 | |
| 1060 | max_bson_size = ctx.max_bson_size |
| 1061 | max_write_batch_size = ctx.max_write_batch_size |
| 1062 | max_message_size = ctx.max_message_size |
| 1063 | |
| 1064 | command_encoded = _dict_to_bson(command, False, opts) |
| 1065 | # When OP_MSG is used unacknowledged we have to check command |
| 1066 | # document size client-side or applications won't be notified. |
| 1067 | if not ack: |
| 1068 | _check_doc_size_limits("bulkWrite", len(command_encoded), max_bson_size + _COMMAND_OVERHEAD) |
| 1069 | |
| 1070 | # Don't include bulkWrite-command-agnostic fields in batch-splitting calculations. |
| 1071 | abridged_keys = ["bulkWrite", "errorsOnly", "ordered"] |
| 1072 | if command.get("bypassDocumentValidation"): |
| 1073 | abridged_keys.append("bypassDocumentValidation") |
| 1074 | if command.get("comment"): |
| 1075 | abridged_keys.append("comment") |
| 1076 | if command.get("let"): |
| 1077 | abridged_keys.append("let") |
| 1078 | command_abridged = {key: command[key] for key in abridged_keys} |
| 1079 | command_len_abridged = len(_dict_to_bson(command_abridged, False, opts)) |
| 1080 | |
| 1081 | # Maximum combined size of the ops and nsInfo document sequences. |
| 1082 | max_doc_sequences_bytes = max_message_size - (_OP_MSG_OVERHEAD + command_len_abridged) |
| 1083 | |
| 1084 | ns_info = {} |
| 1085 | to_send_ops: list[Mapping[str, Any]] = [] |
| 1086 | to_send_ns: list[Mapping[str, str]] = [] |
| 1087 | to_send_ops_encoded: list[bytes] = [] |
| 1088 | to_send_ns_encoded: list[bytes] = [] |
| 1089 | total_ops_length = 0 |
| 1090 | total_ns_length = 0 |
| 1091 | idx = 0 |
| 1092 | |
| 1093 | for (real_op_type, op_doc), namespace in zip(operations, namespaces): |
| 1094 | op_type = real_op_type |
| 1095 | # Check insert/replace document size if unacknowledged. |
| 1096 | if real_op_type == "insert": |
| 1097 | if not ack: |
| 1098 | doc_size = len(_dict_to_bson(op_doc["document"], False, opts)) |
no test coverage detected