Use randomized, truncated exponential backoff in event of conflict
BugzID: 42053
This is a cherry-pick of:
https://github.com/cloudant/couch_replicator/commit/6e8fbb6a3f2622c14ae605c18ec54cbad7d389f3
Conflicts:
src/couch_replicator_manager.erl
diff --git a/src/couch_replicator_manager.erl b/src/couch_replicator_manager.erl
index caae55f..0fcb0c4 100644
--- a/src/couch_replicator_manager.erl
+++ b/src/couch_replicator_manager.erl
@@ -596,11 +596,14 @@
ets:delete(?DB_TO_SEQ,DbName).
-update_rep_doc(RepDbName, RepDocId, KVs) when is_binary(RepDocId) ->
+update_rep_doc(RepDbName, RepDocId, KVs) ->
+ update_rep_doc(RepDbName, RepDocId, KVs, 1).
+
+update_rep_doc(RepDbName, RepDocId, KVs, Wait) when is_binary(RepDocId) ->
try
case open_rep_doc(RepDbName, RepDocId) of
{ok, LastRepDoc} ->
- update_rep_doc(RepDbName, LastRepDoc, KVs);
+ update_rep_doc(RepDbName, LastRepDoc, KVs, Wait * 2);
_ ->
ok
end
@@ -608,10 +611,10 @@
throw:conflict ->
Msg = "Conflict when updating replication document `~s`. Retrying.",
couch_log:error(Msg, [RepDocId]),
- ok = timer:sleep(5),
- update_rep_doc(RepDbName, RepDocId, KVs)
+ ok = timer:sleep(random:uniform(erlang:min(128, Wait)) * 100),
+ update_rep_doc(RepDbName, RepDocId, KVs, Wait * 2)
end;
-update_rep_doc(RepDbName, #doc{body = {RepDocBody}} = RepDoc, KVs) ->
+update_rep_doc(RepDbName, #doc{body = {RepDocBody}} = RepDoc, KVs, _Try) ->
NewRepDocBody = lists:foldl(
fun({K, undefined}, Body) ->
lists:keydelete(K, 1, Body);