Skip to content

Commit

Permalink
FFM-9927 Update MM3 Hash / Fallback to identifier for BB (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
erdirowlands authored Dec 4, 2023
1 parent e62422b commit 91f301b
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 123 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [3.0.0] - 2023-12-04
## ** Breaking for Erlang applications (not affecting Elixir applications) **

- The percentage rollout hash algorithm was slightly different compared to other Feature Flags SDKs, which resulted
in a different bucket allocation for the same target. The overall distribution was the same, but this change ensures
that the same target will get the same allocation per SDK
- if a custom BucketBy field is set on the web app, but it can't be found in a target, then the SDK will fall back
to bucketing by target identifier for that target a warning will be logged

## [2.0.1] - 2023-07-02
### Fixes
- Some SDK dependencies were not getting included in releases created by `mix `
Expand Down Expand Up @@ -150,4 +159,3 @@ Evaluation Rules not yet complete:
- Pre-requisites
- Percentage Rollout


8 changes: 1 addition & 7 deletions rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,4 @@
]
}.

{
shell,
[
% {config, "config/sys.config"},
{apps, [cfclient]}
]
}.
{shell, [{config, "config/sys.config"}, {apps, [cfclient]}]}.
2 changes: 1 addition & 1 deletion src/cfclient.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[
{description, "Harness Feature Flags Server SDK"},
{pkg_name, "harness_ff_erlang_server_sdk"},
{vsn, "2.0.1"},
{vsn, "3.0.0"},
{registered, []},
{mod, {cfclient_app, []}},
{applications, [kernel, stdlib, cfapi, base64url, murmur, jsx, mochiweb]},
Expand Down
18 changes: 14 additions & 4 deletions src/cfclient_evaluator.erl
Original file line number Diff line number Diff line change
Expand Up @@ -387,9 +387,19 @@ search_rules_for_inclusion([Rule | Tail], Target, Config) ->
Distribution when Distribution /= null ->
#{bucketBy := BucketBy, variations := Variations} = Distribution,
#{identifier := Id, name := Name} = Target,
Attributes = maps:get(attributes, Target, #{}),
TargetAttributeValue = get_attribute_value(Attributes, BucketBy, Id, Name),
apply_percentage_rollout(Variations, BucketBy, TargetAttributeValue, 0)
TargetAttributes = maps:get(attributes, Target, #{}),
TargetAttributeValue = get_attribute_value(TargetAttributes, BucketBy, Id, Name),
{FinalTargetAttributeValue, FinalBucketBy} =
case TargetAttributeValue of
<<>> ->
% If the BucketBy field isn't found in the target, then fall back to the ID and log a warning
?LOG_WARNING("BucketBy attribute '~p' not found in target attributes, falling back to 'identifier' ~p", [BucketBy, Id]),
{Id, <<"identifier">>};

_ ->
{TargetAttributeValue, BucketBy}
end,
apply_percentage_rollout(Variations, FinalBucketBy, FinalTargetAttributeValue, 0)
end;

_ -> search_rules_for_inclusion(Tail, Target, Config)
Expand Down Expand Up @@ -557,7 +567,7 @@ apply_percentage_rollout([], _, _, _) -> excluded.

-spec should_rollout(binary(), binary(), integer()) -> boolean().
should_rollout(BucketBy, TargetValue, Percentage) ->
Concatenated = <<TargetValue/binary, ":", BucketBy/binary>>,
Concatenated = <<BucketBy/binary, ":", TargetValue/binary>>,
% Using a pure Elixir library for murmur3
Hash = 'Elixir.Murmur':hash_x86_32(Concatenated),
BucketID = (Hash rem 100) + 1,
Expand Down
2 changes: 1 addition & 1 deletion src/cfclient_metrics_attributes.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
%% Constants for Metrics Data Attribute Values

-define(SDK_TYPE_ATTRIBUTE_VALUE, <<"server">>).
-define(SDK_VERSION_ATTRIBUTE_VALUE, <<"1.1.0">>).
-define(SDK_VERSION_ATTRIBUTE_VALUE, <<"3.0.0">>).
-define(SDK_LANGUAGE_ATTRIBUTE_VALUE, <<"erlang">>).
-define(TARGET_GLOBAL_IDENTIFIER, <<"__global__cf_target">>).
9 changes: 9 additions & 0 deletions src/murmur_example.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-module(murmur_example).

-export([run_hash/0]).

run_hash() ->
Concatenated = "identifier:test",
% Using a pure Elixir library for murmur3
Hash = 'Elixir.Murmur':hash_x86_32(Concatenated),
BucketID = (Hash rem 100) + 1.
12 changes: 6 additions & 6 deletions test/cfclient_evaluator_test_data.erl
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
prerequisite_matches_flag_2/0,
prerequisite_matches_flag_3/0,
generate_targets/2,
percentage_rollout_boolean/2,
percentage_rollout_multi_variate/3
percentage_rollout_boolean/3,
percentage_rollout_multi_variate/4
]
).

Expand Down Expand Up @@ -905,7 +905,7 @@ target_group_for_percentage_rollout() ->
}.


percentage_rollout_boolean(Weight1, Weight2) ->
percentage_rollout_boolean(Weight1, Weight2, BucketBy) ->
#{
defaultServe => #{variation => <<"true">>},
environment => <<"dev">>,
Expand Down Expand Up @@ -937,7 +937,7 @@ percentage_rollout_boolean(Weight1, Weight2) ->
distribution
=>
#{
bucketBy => <<"identifier">>,
bucketBy => BucketBy,
variations
=>
[
Expand All @@ -959,7 +959,7 @@ percentage_rollout_boolean(Weight1, Weight2) ->
version => 4
}.

percentage_rollout_multi_variate(Weight1, Weight2, Weight3) ->
percentage_rollout_multi_variate(Weight1, Weight2, Weight3, BucketBy) ->
#{
defaultServe => #{variation => <<"variation3">>},
environment => <<"dev">>,
Expand Down Expand Up @@ -991,7 +991,7 @@ percentage_rollout_multi_variate(Weight1, Weight2, Weight3) ->
distribution
=>
#{
bucketBy => <<"identifier">>,
bucketBy => BucketBy,
variations
=>
[
Expand Down
Loading

0 comments on commit 91f301b

Please sign in to comment.