Performs message processing.

        :param dict messages: indexed by message id dict with messages data
        :param bool ignore_unknown_message_types: whether to silence exceptions
        :raises UnknownMessageTypeError:

def _process_messages(self, messages, ignore_unknown_message_types=False):
        """Performs message processing.

        :param dict messages: indexed by message id dict with messages data
        :param bool ignore_unknown_message_types: whether to silence exceptions
        :raises UnknownMessageTypeError:
        """
        with self.before_after_send_handling():
            for message_id, message_data in messages.items():
                message_model, dispatch_models = message_data
                try:
                    message_cls = get_registered_message_type(message_model.cls)
                except UnknownMessageTypeError:
                    if ignore_unknown_message_types:
                        continue
                    raise

                message_type_cache = None
                for dispatch in dispatch_models:
                    if not dispatch.message_cache:  # Create actual message text for further usage.
                        try:
                            if message_type_cache is None and not message_cls.has_dynamic_context:
                                # If a message class doesn't depend upon a dispatch data for message compilation,
                                # we'd compile a message just once.
                                message_type_cache = message_cls.compile(message_model, self, dispatch=dispatch)

                            dispatch.message_cache = message_type_cache or message_cls.compile(
                                message_model, self, dispatch=dispatch)

                        except Exception as e:
                            self.mark_error(dispatch, e, message_cls)

                self.send(message_cls, message_model, dispatch_models)