Packages
launchdarkly_server_sdk
2.1.2
3.11.0
3.10.1
3.9.0
3.8.1
3.8.0
3.7.2
3.7.1
3.7.0
3.6.0
3.5.0
3.4.0
3.3.1
3.3.0
3.2.0
3.1.0
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
2.1.2
2.1.1
2.1.0
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.6.0
1.5.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.3
1.1.2
1.1.1
retired
1.1.0
retired
1.0.1
retired
1.0.0
retired
1.0.0-beta4
retired
1.0.0-beta3
retired
1.0.0-beta2
retired
LaunchDarkly SDK for Erlang
Current section
Files
Jump to
Current section
Files
src/ldclient_flag.erl
%%-------------------------------------------------------------------
%% @doc Flag data type
%% @private
%% @end
%%-------------------------------------------------------------------
-module(ldclient_flag).
%% API
-export([new/1]).
-export([new_simple/2]).
-export([get_variation/2]).
%% Types
-type flag() :: #{
debugEventsUntilDate => pos_integer() | null,
deleted => boolean(),
fallthrough => variation_or_rollout(),
key => key(),
offVariation => variation(),
on => boolean(),
prerequisites => [prerequisite()],
rules => [ldclient_rule:rule()],
salt => binary(),
targets => [target()],
contextTargets => [target()],
trackEvents => boolean(),
trackEventsFallthrough => boolean(),
variations => [variation_value()],
version => version()
}.
-type key() :: binary().
%% Flag key
-type variation() :: non_neg_integer() | null.
%% Variation index
-type variation_or_rollout() :: variation() | ldclient_rollout:rollout().
%% Contains either the fixed variation or percent rollout to serve
-type prerequisite() :: #{
key => key(),
variation => variation()
}.
%% Describes a requirement that another feature flag return a specific variation
-type target() :: #{
contextKind => ldclient_context:kind_value(),
values => [ldclient_user:key()],
variation => variation()
}.
%% Describes a set of users who will receive a specific variation
-type variation_value() ::
boolean()
| integer()
| float()
| binary()
| list()
| map().
-type version() :: non_neg_integer().
-export_type([flag/0]).
-export_type([key/0]).
-export_type([prerequisite/0]).
-export_type([target/0]).
-export_type([variation/0]).
-export_type([variation_or_rollout/0]).
-export_type([variation_value/0]).
-export_type([version/0]).
%%===================================================================
%% API
%%===================================================================
-spec new(RawFlagMap :: map()) -> flag().
new(RawFlagMap) ->
FlagTemplate = #{
<<"debugEventsUntilDate">> => null,
<<"deleted">> => false,
<<"fallthrough">> => #{},
<<"key">> => <<>>,
<<"offVariation">> => 0,
<<"on">> => false,
<<"prerequisites">> => [],
<<"rules">> => [],
<<"salt">> => <<>>,
<<"targets">> => [],
<<"contextTargets">> => [],
<<"trackEvents">> => false,
<<"trackEventsFallthrough">> => false,
<<"variations">> => [],
<<"version">> => 0
},
FlagMap = maps:merge(FlagTemplate, RawFlagMap),
new_from_template(FlagMap).
-spec new_simple(Key :: key(), Value :: variation_value()) -> flag().
new_simple(Key, Value) ->
new(#{
<<"key">> => Key,
<<"on">> => true,
<<"variations">> => [Value],
<<"fallthrough">> => #{
<<"variation">> => 0
}
}).
-spec get_variation(Flag :: flag(), VariationIndex :: non_neg_integer()|null) -> term().
get_variation(_Flag, null) -> null;
get_variation(_Flag, Variation) when is_integer(Variation), Variation < 0 -> null;
get_variation(#{variations := Variations}, VariationIndex)
when is_integer(VariationIndex), VariationIndex + 1 > length(Variations) -> null;
get_variation(#{variations := Variations}, VariationIndex) when is_integer(VariationIndex) ->
lists:nth(VariationIndex + 1, Variations).
%%===================================================================
%% Internal functions
%%===================================================================
-spec new_from_template(FlagMap :: map()) -> flag().
new_from_template(#{
<<"debugEventsUntilDate">> := DebugEventsUntilDate,
<<"deleted">> := Deleted,
<<"fallthrough">> := Fallthrough,
<<"key">> := Key,
<<"offVariation">> := OffVariation,
<<"on">> := On,
<<"prerequisites">> := Prerequisites,
<<"rules">> := Rules,
<<"salt">> := Salt,
<<"targets">> := Targets,
<<"contextTargets">> := ContextTargets,
<<"trackEvents">> := TrackEvents,
<<"trackEventsFallthrough">> := TrackEventsFallthrough,
<<"variations">> := Variations,
<<"version">> := Version
}) ->
#{
debugEventsUntilDate => DebugEventsUntilDate,
deleted => Deleted,
fallthrough => parse_variation_or_rollout(Fallthrough),
key => Key,
offVariation => OffVariation,
on => On,
prerequisites => parse_prerequisites(Prerequisites),
rules => parse_rules(Rules),
salt => Salt,
targets => parse_targets(Targets),
contextTargets => parse_targets(ContextTargets),
trackEvents => TrackEvents,
trackEventsFallthrough => TrackEventsFallthrough,
variations => Variations,
version => Version
}.
-spec parse_prerequisites([map()]) -> [prerequisite()].
parse_prerequisites(Prerequisites) ->
F = fun(#{<<"key">> := Key, <<"variation">> := Variation}, Acc) ->
[#{key => Key, variation => Variation}|Acc];
(_, Acc) ->
Acc
end,
lists:foldr(F, [], Prerequisites).
-spec parse_rules([map()]) -> [ldclient_rule:rule()].
parse_rules(Rules) ->
F = fun(#{<<"clauses">> := Clauses} = Rule, Acc) when is_list(Clauses) ->
[ldclient_rule:new(Rule)|Acc];
(_, Acc) ->
Acc
end,
lists:foldr(F, [], Rules).
-spec parse_targets([map()]) -> [target()].
parse_targets(Targets) ->
F = fun(#{<<"values">> := Values, <<"variation">> := Variation} = Target, Acc) ->
[#{
contextKind => maps:get(<<"contextKind">>, Target, <<"user">>),
values => Values,
variation => Variation
}|Acc];
(_, Acc) ->
Acc
end,
lists:foldr(F, [], Targets).
-spec parse_variation_or_rollout(map()) -> variation_or_rollout().
parse_variation_or_rollout(#{<<"variation">> := Variation}) when is_integer(Variation) -> Variation;
parse_variation_or_rollout(#{<<"rollout">> := #{<<"variations">> := Variations} = Rollout}) when is_list(Variations) ->
ldclient_rollout:new(Rollout);
parse_variation_or_rollout(Variation) when is_integer(Variation) -> Variation;
parse_variation_or_rollout(_) -> ldclient_rollout:new(#{<<"variations">> => []}).