Example #1
0
    def _update_many(cls, documents: List[dict]) -> (List[dict], List[dict]):
        previous_documents = []
        new_documents = []
        revision = cls._increment(*REVISION_COUNTER)
        for document in documents:
            document_keys = cls._to_primary_keys_model(document)
            document_keys[cls.valid_until_revision.name] = -1
            previous_document = cls.__collection__.find_one(
                document_keys, projection={"_id": False})
            if not previous_document:
                raise ModelCouldNotBeFound(document_keys)

            # Set previous version as expired (insert previous as expired)
            cls.__collection__.insert_one({
                **previous_document, cls.valid_until_revision.name:
                revision
            })

            # Update valid version (update previous)
            document[cls.valid_since_revision.name] = revision
            document[cls.valid_until_revision.name] = -1
            new_document = cls.__collection__.find_one_and_update(
                document_keys,
                {"$set": document},
                return_document=pymongo.ReturnDocument.AFTER,
            )

            previous_documents.append(previous_document)
            new_documents.append(new_document)

        if cls.audit_model:
            cls.audit_model.audit_update(revision)
        return previous_documents, new_documents
Example #2
0
    def _update_one(cls, document: dict) -> (dict, dict):
        document_keys = cls._to_primary_keys_model(document)
        previous_document = cls.__collection__.find_one(document_keys)
        if not previous_document:
            raise ModelCouldNotBeFound(document_keys)

        new_document = cls.__collection__.find_one_and_update(
            document_keys,
            {"$set": document},
            return_document=pymongo.ReturnDocument.AFTER,
        )
        if cls.audit_model:
            cls.audit_model.audit_update(new_document)
        return previous_document, new_document
Example #3
0
    def update_all(cls, rows: List[dict]) -> (List[dict], List[dict]):
        """
        Update models formatted as a list of dictionaries.

        :raises ValidationFailed in case Marshmallow validation fail.
        :returns A tuple containing previous models formatted as a list of dictionaries (first item)
        and new models formatted as a list of dictionaries (second item).
        """
        if not rows:
            raise ValidationFailed({}, message="No data provided.")
        previous_rows = []
        new_rows = []
        new_models = []
        for row in rows:
            if not isinstance(row, dict):
                raise ValidationFailed(row, message="Must be a dictionary.")
            try:
                previous_model = cls.schema().get_instance(row)
            except exc.sa_exc.DBAPIError:
                cls._handle_connection_failure()
            if not previous_model:
                raise ModelCouldNotBeFound(row)
            previous_row = _model_field_values(previous_model)
            try:
                new_model = cls.schema().load(row,
                                              instance=previous_model,
                                              partial=True,
                                              session=cls._session)
            except ValidationError as e:
                raise ValidationFailed(row, e.messages)
            new_row = _model_field_values(new_model)

            previous_rows.append(previous_row)
            new_rows.append(new_row)
            new_models.append(new_model)

        try:
            cls._session.add_all(new_models)
            if cls.audit_model:
                for new_row in new_rows:
                    cls.audit_model.audit_update(new_row)
            cls._session.commit()
            return previous_rows, new_rows
        except exc.sa_exc.DBAPIError:
            cls._session.rollback()
            cls._handle_connection_failure()
        except Exception:
            cls._session.rollback()
            raise
Example #4
0
    def _update_many(cls, documents: List[dict]) -> (List[dict], List[dict]):
        previous_documents = []
        new_documents = []
        for document in documents:
            document_keys = cls._to_primary_keys_model(document)
            previous_document = cls.__collection__.find_one(document_keys)
            if not previous_document:
                raise ModelCouldNotBeFound(document_keys)

            new_document = cls.__collection__.find_one_and_update(
                document_keys,
                {"$set": document},
                return_document=pymongo.ReturnDocument.AFTER,
            )
            previous_documents.append(previous_document)
            new_documents.append(new_document)
            if cls.audit_model:
                cls.audit_model.audit_update(new_document)
        return previous_documents, new_documents