def _parse_sync_stream(self, data, return_doc_cb, ensure_callback=None): parts = data.splitlines() # one at a time if not parts or parts[0] != '[': raise BrokenSyncStream data = parts[1:-1] comma = False if data: line, comma = utils.check_and_strip_comma(data[0]) res = json.loads(line) if ensure_callback and 'replica_uid' in res: ensure_callback(res['replica_uid']) for entry in data[1:]: if not comma: # missing in between comma raise BrokenSyncStream line, comma = utils.check_and_strip_comma(entry) entry = json.loads(line) doc = Document(entry['id'], entry['rev'], entry['content']) return_doc_cb(doc, entry['gen'], entry['trans_id']) if parts[-1] != ']': try: partdic = json.loads(parts[-1]) except ValueError: pass else: if isinstance(partdic, dict): self._error(partdic) raise BrokenSyncStream if not data or comma: # no entries or bad extra comma raise BrokenSyncStream return res
def post_put(self, id, rev, content, gen, trans_id, number_of_docs, doc_idx): """ Put one incoming document into the server replica. :param id: The id of the incoming document. :type id: str :param rev: The revision of the incoming document. :type rev: str :param content: The content of the incoming document. :type content: dict :param gen: The source replica generation corresponding to the revision of the incoming document. :type gen: int :param trans_id: The source replica transaction id corresponding to the revision of the incoming document. :type trans_id: str :param number_of_docs: The total amount of documents sent on this sync session. :type number_of_docs: int :param doc_idx: The index of the current document. :type doc_idx: int """ doc = Document(id, rev, content) self._staging.append((doc, gen, trans_id, number_of_docs, doc_idx))
def test_put_doc(self): self.response_val = {'rev': 'doc-rev'}, {} doc = Document('doc-id', None, '{"v": 1}') res = self.db.put_doc(doc) self.assertEqual('doc-rev', res) self.assertEqual('doc-rev', doc.rev) self.assertEqual(('PUT', ['doc', 'doc-id'], {}, '{"v": 1}', 'application/json'), self.got) self.response_val = {'rev': 'doc-rev-2'}, {} doc.content = {"v": 2} res = self.db.put_doc(doc) self.assertEqual('doc-rev-2', res) self.assertEqual('doc-rev-2', doc.rev) self.assertEqual(('PUT', ['doc', 'doc-id'], {'old_rev': 'doc-rev'}, '{"v": 2}', 'application/json'), self.got)
def put(self, content, old_rev=None): doc = Document(self.id, old_rev, content) doc_rev = self.db.put_doc(doc) if old_rev is None: status = 201 # created else: status = 200 self.responder.send_response_json(status, rev=doc_rev)
def test_doc_ids_needing_quoting(self): db0 = self.request_state._create_database('db0') db = http_database.HTTPDatabase.open_database(self.getURL('db0'), create=False) doc = Document('%fff', None, '{}') db.put_doc(doc) self.assertGetDoc(db0, '%fff', doc.rev, '{}', False) self.assertGetDoc(db, '%fff', doc.rev, '{}', False)
def test_delete_doc(self): self.response_val = {'rev': 'doc-rev-gone'}, {} doc = Document('doc-id', 'doc-rev', None) self.db.delete_doc(doc) self.assertEqual('doc-rev-gone', doc.rev) self.assertEqual(('DELETE', ['doc', 'doc-id'], { 'old_rev': 'doc-rev' }, None, None), self.got)
def test_put_doc(self): self.response_val = {'rev': 'doc-rev'}, {} doc = Document('doc-id', None, '{"v": 1}') res = self.db.put_doc(doc) self.assertEqual('doc-rev', res) self.assertEqual('doc-rev', doc.rev) self.assertEqual( ('PUT', ['doc', 'doc-id'], {}, '{"v": 1}', 'application/json'), self.got) self.response_val = {'rev': 'doc-rev-2'}, {} doc.content = {"v": 2} res = self.db.put_doc(doc) self.assertEqual('doc-rev-2', res) self.assertEqual('doc-rev-2', doc.rev) self.assertEqual(('PUT', ['doc', 'doc-id'], { 'old_rev': 'doc-rev' }, '{"v": 2}', 'application/json'), self.got)
def _prune_conflicts(self, doc, doc_vcr): if self._has_conflicts(doc.doc_id): autoresolved = False remaining_conflicts = [] cur_conflicts = self._conflicts[doc.doc_id] for c_rev, c_doc in cur_conflicts: c_vcr = vectorclock.VectorClockRev(c_rev) if doc_vcr.is_newer(c_vcr): continue if doc.same_content_as(Document(doc.doc_id, c_rev, c_doc)): doc_vcr.maximize(c_vcr) autoresolved = True continue remaining_conflicts.append((c_rev, c_doc)) if autoresolved: doc_vcr.increment(self._replica_uid) doc.rev = doc_vcr.as_str() self._replace_conflicts(doc, remaining_conflicts)
def make_document_for_test(test, doc_id, rev, content, has_conflicts=False): return Document(doc_id, rev, content, has_conflicts=has_conflicts)
def post_stream_entry(self, id, rev, content, gen, trans_id): doc = Document(id, rev, content) self.sync_exch.insert_doc_from_source(doc, gen, trans_id)
def delete(self, old_rev=None): doc = Document(self.id, old_rev, None) self.db.delete_doc(doc) self.responder.send_response_json(200, rev=doc.rev)