Beispiel #1
0
    def save_document(self, doc):
        assert IDocument.providedBy(doc) or isinstance(doc, dict), repr(doc)
        try:
            self._lock_notifications()

            serialized = self._serializer.convert(doc)
            if IDocument.providedBy(doc):
                following_attachments = dict(
                    (name, attachment) for name, attachment
                    in doc.get_attachments().iteritems()
                    if not attachment.saved)
                doc_id = doc.doc_id
            else:
                following_attachments = dict()
                doc_id = doc.get('_id')
            resp = yield self._database.save_doc(serialized, doc_id,
                                                 following_attachments)
            self._update_id_and_rev(resp, doc)
            for attachment in following_attachments.itervalues():
                attachment.set_saved()

            # now process all the documents which have been registered to
            # be saved together with this document
            if IDocument.providedBy(doc):
                while doc.links.to_save:
                    to_link, linker_roles, linkee_roles = (
                        doc.links.to_save.pop(0))
                    to_link.links.create(doc=doc, linker_roles=linker_roles,
                                         linkee_roles=linkee_roles)
                    yield self.save_document(to_link)

            defer.returnValue(doc)
        finally:
            self._unlock_notifications()
Beispiel #2
0
    def _iterate_on_update(self, _document, _method, args, keywords):
        if IDocument.providedBy(_document):
            doc_id = _document.doc_id
            rev = _document.rev
        else:
            doc_id = _document['_id']
            rev = _document['_rev']

        try:
            result = _method(_document, *args, **keywords)
        except ResignFromModifying:
            return _document
        if result is None:
            d = self.delete_document(_document)
        else:
            d = self.save_document(result)
        if (IDocument.providedBy(_document) and
            _document.conflict_resolution_strategy ==
            ConflictResolutionStrategy.merge):
            update_log = document.UpdateLog(
                handler=_method,
                args=args,
                keywords=keywords,
                rev_from=rev,
                timestamp=time.time())
            d.addCallback(lambda doc:
                          defer.DeferredList([defer.succeed(doc),
                                              self.get_database_tag(),
                                              self.get_update_seq()]))
            d.addCallback(self._log_update, update_log)
        d.addErrback(self._errback_on_update, doc_id,
                     _method, args, keywords)
        return d
Beispiel #3
0
    def save_document(self, doc):
        doc = IDocument(doc)

        serialized = self._serializer.convert(doc)
        resp = yield self._database.save_doc(serialized, doc.doc_id)
        self._update_id_and_rev(resp, doc)

        for name, attachment in doc.get_attachments().iteritems():
            if not attachment.saved:
                resp = yield self._database.save_attachment(
                    doc.doc_id, doc.rev, attachment)
                self._update_id_and_rev(resp, doc)
                attachment.set_saved()
        defer.returnValue(doc)
Beispiel #4
0
 def update_document_ex(self, doc, _method, args=tuple(), keywords=dict()):
     if not IDocument.providedBy(doc):
         d = self.get_document(doc)
     else:
         d = defer.succeed(doc)
     d.addCallback(self._iterate_on_update, _method, args, keywords)
     return d
Beispiel #5
0
def solve(connection, doc_id):
    connection.info('Solving conflicts for document: %s', doc_id)

    plain_doc = yield connection.get_document(doc_id, raw=True,
                                              conflicts=True)
    if '_conflicts' not in plain_doc:
        connection.debug('Document:%s is not in state conflict, aborting.',
                         doc_id)
        return
    doc = connection._unserializer.convert(plain_doc)
    if not IDocument.providedBy(doc):
        handler = _solve_alert
    else:
        strategy_handlers = {
            ConflictResolutionStrategy.db_winner: _solve_db_winner,
            ConflictResolutionStrategy.alert: _solve_alert,
            ConflictResolutionStrategy.merge: _solve_merge}
        s = type(doc).conflict_resolution_strategy
        handler = strategy_handlers.get(s, _solve_alert)
        connection.debug("Using %s strategy", handler.__name__)

    try:
        yield handler(connection, doc, plain_doc['_conflicts'])
        connection.debug("Solving conflict for document %s completed", doc_id)
    except UnsolvableConflict:
        raise
    except Exception as e:
        error.handle_exception(None, e, "Failed solving conflict")
        raise UnsolvableConflict(str(e), doc)
Beispiel #6
0
 def keys(doc_id, type_name=None):
     if IDocument.providedBy(doc_id):
         doc_id = doc_id.doc_id
     if type_name is not None:
         return dict(key=(doc_id, type_name))
     else:
         return dict(startkey=(doc_id, ), endkey=(doc_id, {}))
Beispiel #7
0
 def initial_data(self, doc):
     if callable(doc) and IDocument.implementedBy(doc):
         doc = doc()
     doc = IDocument(doc)
     if doc.doc_id is None:
         raise ValueError("Initial documents should have doc_id fixed (None)")
     self._initial_data.register(doc, application=self)
     return doc
Beispiel #8
0
 def _update_id_and_rev(self, resp, doc):
     if IDocument.providedBy(doc):
         doc.doc_id = unicode(resp.get('id', None))
         doc.rev = unicode(resp.get('rev', None))
         self._notice_doc_revision(doc)
     else:
         doc['_id'] = unicode(resp.get('id', None))
         doc['_rev'] = unicode(resp.get('rev', None))
     return doc
Beispiel #9
0
 def _notice_doc_revision(self, doc):
     if IDocument.providedBy(doc):
         doc_id = doc.doc_id
         rev = doc.rev
     else:
         doc_id = doc['_id']
         rev = doc['_rev']
     self.log('Storing knowledge about doc rev. ID: %r, REV: %r',
              doc_id, rev)
     self._known_revisions[doc_id] = _parse_doc_revision(rev)
     return doc
Beispiel #10
0
 def copy_document(self, doc_or_id, destination_id, rev=None):
     if isinstance(doc_or_id, (str, unicode)):
         doc_id = doc_or_id
     elif IDocument.providedBy(doc_or_id):
         doc_id = doc_or_id.doc_id
     elif isinstance(doc_or_id, dict):
         doc_id = doc_or_id['_id']
     else:
         raise TypeError(type(doc_or_id))
     if not doc_id:
         raise ValueError("Cannot determine doc id from %r" % (doc_or_id, ))
     return self._database.copy_doc(doc_id, destination_id, rev)
Beispiel #11
0
    def _solve_err(self, state, fail):
        if fail.check(conflicts.UnsolvableConflict):
            doc = fail.value.doc
            if IDocument.providedBy(doc):
                doc_id = doc.doc_id
            else:
                doc_id = doc['_id']

            state.unsolvable_conflicts.add(doc_id)
            self.warning('Cannot solve conflict for document id: %s. '
                         'Reason: %s', doc_id, fail.value)

            self.raise_alert(ALERT_NAME, ', '.join(state.unsolvable_conflicts))
        else:
            error.handle_failure(self, fail, 'Failed solving conflict.')
            msg = error.get_failure_message(fail)
            self.raise_alert(ALERT_NAME, msg, severity=alert.Severity.critical)
Beispiel #12
0
    def create(self, doc_id=None, linker_roles=None,
               linkee_roles=None, type_name=None, doc=None):
        if doc is not None:
            if IDocument.providedBy(doc):
                doc_id = doc.doc_id or doc_id
                type_name = doc.type_name
            elif isinstance(doc, dict):
                doc_id = doc['_id']
            else:
                raise TypeError(doc)
        if doc_id is None:
            raise ValueError("Either pass doc_id or saved document instance")
        if type_name is None:
            raise ValueError("Type name is needed to create a link")
        if linker_roles and not isinstance(linker_roles, list):
            raise TypeError(linker_roles)
        if linkee_roles and not isinstance(linkee_roles, list):
            raise TypeError(linkee_roles)

        self.remove(doc_id, noraise=True)
        self._links.append([type_name, doc_id,
                            linker_roles or list(), linkee_roles or list()])
Beispiel #13
0
    def delete_document(self, doc):
        if IDocument.providedBy(doc):
            body = {
                "_id": doc.doc_id,
                "_rev": doc.rev,
                "_deleted": True,
                ".type": unicode(doc.type_name)}
            for field in type(doc)._fields:
                if field.meta('keep_deleted'):
                    body[field.serialize_as] = getattr(doc, field.name)
        elif isinstance(doc, dict):
            body = {
                "_id": doc["_id"],
                "_rev": doc["_rev"],
                "_deleted": True}
        else:
            raise ValueError(repr(doc))

        serialized = self._serializer.convert(body)
        self._lock_notifications()
        d = self._database.save_doc(serialized, body["_id"])
        d.addCallback(self._update_id_and_rev, doc)
        d.addBoth(defer.bridge_param, self._unlock_notifications)
        return d
Beispiel #14
0
 def __init__(self, reference, message):
     Response.__init__(self, ResponseTypes.created, message)
     self.reference = reference if reference is not None else None
     if IDocument.providedBy(reference):
         self.id = reference.doc_id
Beispiel #15
0
 def reload_document(self, doc):
     assert IDocument.providedBy(doc), \
            "Incorrect type: %r, expected IDocument" % (type(doc), )
     return self.get_document(doc.doc_id)