···9999100100 # Note: this resends *all* requests if a single one fails due to too_old/too_new
101101 # If a read touches a large number of servers this could become a problem
102102- backoff(nil, fn acc ->
102102+ retry_acc(nil, fn acc ->
103103 case acc || get_shards.() do
104104 {:ok, shards} = shard_result ->
105105 case do_multi_read(txn, keys, shards) do
···185185 end
186186 end
187187188188- backoff(nil, fn acc ->
188188+ retry_acc(nil, fn acc ->
189189 case acc || get_ranges.() do
190190 {:ok, ranges} = acc ->
191191 case do_read_split_range(txn, ranges) do
+29
lib/utils.ex
···376376 |> Enum.sort()
377377 end
378378379379+ @spec retry_acc(term, (term -> {:cont, term, term} | {:halt, term}), pos_integer) :: term
380380+ def retry_acc(acc, fun, count \\ 6) when is_function(fun, 1) and is_integer(count) and count > 0 do
381381+ do_retry_acc(acc, fun, count, 1)
382382+ end
383383+384384+ defp do_retry_acc(acc, fun, count, attempt) do
385385+ assert attempt <= count
386386+387387+ case fun.(acc) do
388388+ {:cont, acc, error} ->
389389+ case attempt < count do
390390+ true ->
391391+ delay_ms = backoff_delay(attempt)
392392+ SimProcess.sleep(delay_ms)
393393+ do_retry_acc(acc, fun, count, attempt + 1)
394394+ false ->
395395+ error
396396+ end
397397+398398+ {:halt, result} ->
399399+ result
400400+ end
401401+ end
402402+403403+ defp backoff_delay(attempt) do
404404+ # TODO: * 10
405405+ Integer.pow(2, attempt)
406406+ end
407407+379408 @spec backoff(term, ({:cont, term, term} | {:halt, term} -> term), non_neg_integer, non_neg_integer) :: term
380409 def backoff(acc \\ nil, fun, count \\ 6, attempt \\ 0, last_error \\ nil)
381410