summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/changes/feature_5388_avoid-concurrent-syncs-update-handler-conflict2
-rw-r--r--common/src/leap/soledad/common/couch.py20
2 files changed, 14 insertions, 8 deletions
diff --git a/common/changes/feature_5388_avoid-concurrent-syncs-update-handler-conflict b/common/changes/feature_5388_avoid-concurrent-syncs-update-handler-conflict
new file mode 100644
index 00000000..d0c820db
--- /dev/null
+++ b/common/changes/feature_5388_avoid-concurrent-syncs-update-handler-conflict
@@ -0,0 +1,2 @@
+ o Avoid concurrent syncs problem by adding a lock for PUTting to the sync
+ log update handler (#5388).
diff --git a/common/src/leap/soledad/common/couch.py b/common/src/leap/soledad/common/couch.py
index c0ebc425..ebe8477f 100644
--- a/common/src/leap/soledad/common/couch.py
+++ b/common/src/leap/soledad/common/couch.py
@@ -30,6 +30,7 @@ import threading
from StringIO import StringIO
+from collections import defaultdict
from couchdb.client import Server
@@ -338,6 +339,8 @@ class CouchDatabase(CommonBackend):
# We spawn threads to parallelize the CouchDatabase.get_docs() method
MAX_GET_DOCS_THREADS = 20
+ update_handler_lock = defaultdict(threading.Lock)
+
class _GetDocThread(threading.Thread):
"""
A thread that gets a document from a database.
@@ -1133,13 +1136,14 @@ class CouchDatabase(CommonBackend):
ddoc_path = ['_design', 'syncs', '_update', 'put', 'u1db_sync_log']
res = self._database.resource(*ddoc_path)
try:
- res.put_json(
- body={
- 'other_replica_uid': other_replica_uid,
- 'other_generation': other_generation,
- 'other_transaction_id': other_transaction_id,
- },
- headers={'content-type': 'application/json'})
+ with CouchDatabase.update_handler_lock[self._get_replica_uid()]:
+ res.put_json(
+ body={
+ 'other_replica_uid': other_replica_uid,
+ 'other_generation': other_generation,
+ 'other_transaction_id': other_transaction_id,
+ },
+ headers={'content-type': 'application/json'})
except ResourceNotFound as e:
raise_missing_design_doc_error(e, ddoc_path)
@@ -1367,7 +1371,7 @@ class CouchDatabase(CommonBackend):
if save_conflict:
self._force_doc_sync_conflict(doc)
if replica_uid is not None and replica_gen is not None:
- self._do_set_replica_gen_and_trans_id(
+ self._set_replica_gen_and_trans_id(
replica_uid, replica_gen, replica_trans_id)
# update info
old_doc.rev = doc.rev