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);