1%% @author Couchbase <info@couchbase.com>
2%% @copyright 2017-2018 Couchbase, Inc.
3%%
4%% Licensed under the Apache License, Version 2.0 (the "License");
5%% you may not use this file except in compliance with the License.
6%% You may obtain a copy of the License at
7%%
8%%      http://www.apache.org/licenses/LICENSE-2.0
9%%
10%% Unless required by applicable law or agreed to in writing, software
11%% distributed under the License is distributed on an "AS IS" BASIS,
12%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13%% See the License for the specific language governing permissions and
14%% limitations under the License.
15%%
16-module(backoff).
17
18-export_type([backoff/0]).
19
20-export([new/1]).
21-export([get_timeout/1, reset/1, next/1]).
22
23-include("cut.hrl").
24
25-record(backoff, { initial    :: pos_integer(),
26                   threshold  :: non_neg_integer(),
27                   multiplier :: float(),
28
29                   current_timeout :: pos_integer() }).
30
31-type backoff() :: #backoff{}.
32
33new(Props) ->
34    {initial, Initial}     = lists:keyfind(initial, 1, Props),
35    {threshold, Threshold} = lists:keyfind(threshold, 1, Props),
36    Multiplier             = proplists:get_value(multiplier, Props, 2),
37
38    true = (Initial > 0),
39    true = (Threshold > Initial),
40    true = (Multiplier > 1),
41
42    #backoff{initial    = Initial,
43             threshold  = Threshold,
44             multiplier = Multiplier,
45
46             current_timeout = Initial}.
47
48reset(#backoff{initial = Initial} = Backoff) ->
49    Backoff#backoff{current_timeout = Initial}.
50
51next(#backoff{multiplier      = Multiplier,
52              threshold       = Threshold,
53              current_timeout = Timeout} = Backoff) ->
54
55    NewTimeout0 = trunc(Timeout * Multiplier),
56    NewTimeout  = min(Threshold, NewTimeout0),
57
58    Backoff#backoff{current_timeout = NewTimeout}.
59
60get_timeout(#backoff{current_timeout = Timeout}) ->
61    Timeout.
62