kameleoon-client-ruby 3.8.0 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/kameleoon/configuration/data_file.rb +21 -3
- data/lib/kameleoon/configuration/feature_flag.rb +7 -5
- data/lib/kameleoon/configuration/me_group.rb +19 -0
- data/lib/kameleoon/kameleoon_client.rb +40 -15
- data/lib/kameleoon/utils.rb +4 -0
- data/lib/kameleoon/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d0ea98aa7ca7ea1585f83f6bd231aa577a774124b4332d18ca4e2c2649bfbc2
|
4
|
+
data.tar.gz: ec43717ed1dd3a61828a9c062f10040a7e214e070f30f6deb2a76bec9d60fb76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bec6bd1d823d247b5b1e561e621f454e4d451bec12fb1312dc2a9f348f1e2ccbcc884e6927bae254da107e6314e4d91acad9bb1ef67012d96b62a34253f2978f
|
7
|
+
data.tar.gz: d5f5c2c4d85b5d2f706d35fc77f3bc5ce8b6e24ce56413e5d9086fd95aae0d8adf1bbe37a6b5d041f389575db0c8c3815e005a78a7a9d45f255a9325b4f11c46
|
@@ -3,15 +3,16 @@
|
|
3
3
|
require 'kameleoon/configuration/custom_data_info'
|
4
4
|
require 'kameleoon/configuration/experiment'
|
5
5
|
require 'kameleoon/configuration/feature_flag'
|
6
|
+
require 'kameleoon/configuration/me_group'
|
6
7
|
require 'kameleoon/configuration/settings'
|
7
8
|
require 'kameleoon/logging/kameleoon_logger'
|
8
9
|
|
9
10
|
module Kameleoon
|
10
11
|
module Configuration
|
11
12
|
class DataFile
|
12
|
-
attr_reader :settings, :feature_flags, :
|
13
|
-
:rule_info_by_exp_id, :variation_by_id, :custom_data_info,
|
14
|
-
:holdout
|
13
|
+
attr_reader :settings, :feature_flags, :me_groups, :has_any_targeted_delivery_rule, :feature_flag_by_id,
|
14
|
+
:rule_by_segment_id, :rule_info_by_exp_id, :variation_by_id, :custom_data_info,
|
15
|
+
:experiment_ids_with_js_css_variable, :holdout
|
15
16
|
|
16
17
|
def to_s
|
17
18
|
'DataFile{' \
|
@@ -51,6 +52,7 @@ module Kameleoon
|
|
51
52
|
Logging::KameleoonLogger.debug('CALL: DataFile.init_default')
|
52
53
|
@settings = Settings.new
|
53
54
|
@feature_flags = {}
|
55
|
+
@me_groups = {}
|
54
56
|
@has_any_targeted_delivery_rule = false
|
55
57
|
@custom_data_info = Kameleoon::Configuration::CustomDataInfo.new(nil)
|
56
58
|
Logging::KameleoonLogger.debug('RETURN: DataFile.init_default')
|
@@ -64,6 +66,7 @@ module Kameleoon
|
|
64
66
|
ff = FeatureFlag.new(raw)
|
65
67
|
@feature_flags[ff.feature_key] = ff
|
66
68
|
end
|
69
|
+
@me_groups = make_me_groups(@feature_flags)
|
67
70
|
@has_any_targeted_delivery_rule = any_targeted_delivery_rule?
|
68
71
|
@custom_data_info = CustomDataInfo.new(configuration['customData'])
|
69
72
|
@holdout = Experiment.from_json(configuration['holdout']) if configuration.include?('holdout')
|
@@ -101,6 +104,21 @@ module Kameleoon
|
|
101
104
|
@experiment_ids_with_js_css_variable.freeze
|
102
105
|
end
|
103
106
|
|
107
|
+
def make_me_groups(feature_flags)
|
108
|
+
me_group_lists = {}
|
109
|
+
feature_flags.each_value do |feature_flag|
|
110
|
+
next if feature_flag.me_group_name.nil?
|
111
|
+
|
112
|
+
me_group_list = me_group_lists[feature_flag.me_group_name]
|
113
|
+
if me_group_list
|
114
|
+
me_group_list.push(feature_flag)
|
115
|
+
else
|
116
|
+
me_group_lists[feature_flag.me_group_name] = [feature_flag]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
me_group_lists.transform_values { |me_group_list| MEGroup.new(me_group_list) }
|
120
|
+
end
|
121
|
+
|
104
122
|
def feature_flag_variable_js_css?(feature_flag)
|
105
123
|
feature_flag.variations.first&.variables&.any? do |variable|
|
106
124
|
%w[JS CSS].include?(variable.type)
|
@@ -8,7 +8,7 @@ module Kameleoon
|
|
8
8
|
module Configuration
|
9
9
|
# Class for manage all feature flags with rules
|
10
10
|
class FeatureFlag
|
11
|
-
attr_accessor :id, :feature_key, :variations, :default_variation_key, :environment_enabled, :rules
|
11
|
+
attr_accessor :id, :feature_key, :variations, :default_variation_key, :me_group_name, :environment_enabled, :rules
|
12
12
|
|
13
13
|
def self.create_from_array(array)
|
14
14
|
array&.map { |it| FeatureFlag.new(it) }
|
@@ -16,10 +16,11 @@ module Kameleoon
|
|
16
16
|
|
17
17
|
def to_s
|
18
18
|
'FeatureFlag{' \
|
19
|
-
"id:#{@id},
|
20
|
-
"feature_key
|
21
|
-
"environment_enabled:#{@environment_enabled},
|
22
|
-
"default_variation_key
|
19
|
+
"id:#{@id}," \
|
20
|
+
"feature_key:'#{@feature_key}'," \
|
21
|
+
"environment_enabled:#{@environment_enabled}," \
|
22
|
+
"default_variation_key:'#{@default_variation_key}'," \
|
23
|
+
"me_group_name:'#{@me_group_name}'," \
|
23
24
|
"rules:#{@rules.size}" \
|
24
25
|
'}'
|
25
26
|
end
|
@@ -29,6 +30,7 @@ module Kameleoon
|
|
29
30
|
@feature_key = hash['featureKey']
|
30
31
|
@variations = Variation.create_from_array(hash['variations'])
|
31
32
|
@default_variation_key = hash['defaultVariationKey']
|
33
|
+
@me_group_name = hash['mutuallyExclusiveGroup']
|
32
34
|
@environment_enabled = hash['environmentEnabled']
|
33
35
|
@rules = Rule.create_from_array(hash['rules'])
|
34
36
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kameleoon
|
4
|
+
module Configuration
|
5
|
+
class MEGroup
|
6
|
+
attr_reader :feature_flags
|
7
|
+
|
8
|
+
def initialize(feature_flags)
|
9
|
+
@feature_flags = feature_flags.sort { |a, b| a.id <=> b.id }
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_feature_flag_by_hash(hash)
|
13
|
+
idx = (hash * @feature_flags.size).to_i
|
14
|
+
idx = @feature_flags.size - 1 if idx >= @feature_flags.size
|
15
|
+
@feature_flags[idx]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -922,37 +922,62 @@ module Kameleoon
|
|
922
922
|
forced_variation = visitor&.get_forced_feature_variation(feature_flag.feature_key)
|
923
923
|
if forced_variation
|
924
924
|
eval_exp = EvaluatedExperiment.from_forced_variation(forced_variation)
|
925
|
-
elsif visitor_not_in_holdout?(visitor, visitor_code, track, save)
|
925
|
+
elsif visitor_not_in_holdout?(visitor, visitor_code, track, save) && \
|
926
|
+
ff_unrestricted_by_me_group?(visitor, visitor_code, feature_flag)
|
926
927
|
eval_exp = _calculate_variation_key_for_feature(visitor_code, feature_flag)
|
927
928
|
end
|
928
929
|
save_variation(visitor_code, eval_exp, track: track) if save && !forced_variation&.simulated
|
929
930
|
Logging::KameleoonLogger.debug(
|
930
931
|
"RETURN: KameleoonClient.evaluate(visitor, visitor_code: '%s', feature_flag: %s, track: %s, save: %s)" \
|
931
|
-
' -> (eval_exp: %s)',
|
932
|
-
visitor_code, feature_flag, track, save, eval_exp
|
932
|
+
' -> (eval_exp: %s)', visitor_code, feature_flag, track, save, eval_exp
|
933
933
|
)
|
934
934
|
eval_exp
|
935
935
|
end
|
936
936
|
|
937
|
+
def ff_unrestricted_by_me_group?(visitor, visitor_code, feature_flag)
|
938
|
+
return true if feature_flag.me_group_name.nil?
|
939
|
+
|
940
|
+
Logging::KameleoonLogger.debug(
|
941
|
+
"CALL: KameleoonClient.ff_unrestricted_by_me_group?(visitor, visitor_code: '%s', feature_flag: %s)",
|
942
|
+
visitor_code, feature_flag
|
943
|
+
)
|
944
|
+
unrestricted = true
|
945
|
+
me_group = @data_manager.data_file.me_groups[feature_flag.me_group_name]
|
946
|
+
if me_group
|
947
|
+
code_for_hash = get_code_for_hash(visitor, visitor_code)
|
948
|
+
me_group_hash = Utils::Hasher.obtain_hash_for_me_group(code_for_hash, feature_flag.me_group_name)
|
949
|
+
Logging::KameleoonLogger.debug(
|
950
|
+
"Calculated ME group hash %s for code: '%s', meGroup: '%s'",
|
951
|
+
me_group_hash, code_for_hash, feature_flag.me_group_name
|
952
|
+
)
|
953
|
+
unrestricted = me_group.get_feature_flag_by_hash(me_group_hash) == feature_flag
|
954
|
+
end
|
955
|
+
Logging::KameleoonLogger.debug(
|
956
|
+
"RETURN: KameleoonClient.ff_unrestricted_by_me_group?(visitor, visitor_code: '%s', feature_flag: %s)" \
|
957
|
+
' -> (unrestricted: %s)', visitor_code, feature_flag, unrestricted
|
958
|
+
)
|
959
|
+
unrestricted
|
960
|
+
end
|
961
|
+
|
937
962
|
def visitor_not_in_holdout?(visitor, visitor_code, track, save)
|
963
|
+
holdout = @data_manager.data_file.holdout
|
964
|
+
return true if holdout.nil?
|
965
|
+
|
938
966
|
in_holdout_variation_key = 'in-holdout'
|
939
967
|
Logging::KameleoonLogger.debug(
|
940
968
|
"CALL: KameleoonClient.visitor_not_in_holdout?(visitor, visitor_code: '%s', track: %s, save: %s)",
|
941
969
|
visitor_code, track, save
|
942
970
|
)
|
943
|
-
holdout = @data_manager.data_file.holdout
|
944
971
|
is_not_in_holdout = true
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
save_variation(visitor_code, eval_exp, track: track)
|
955
|
-
end
|
972
|
+
code_for_hash = get_code_for_hash(visitor, visitor_code)
|
973
|
+
variation_hash = Utils::Hasher.obtain(code_for_hash, holdout.id)
|
974
|
+
Logging::KameleoonLogger.debug("Calculated holdout hash %s for code '%s'", variation_hash, code_for_hash)
|
975
|
+
var_by_exp = holdout.get_variation(variation_hash)
|
976
|
+
unless var_by_exp.nil?
|
977
|
+
is_not_in_holdout = var_by_exp.variation_key != in_holdout_variation_key
|
978
|
+
if save
|
979
|
+
eval_exp = EvaluatedExperiment.new(var_by_exp, holdout, Configuration::RuleType::EXPERIMENTATION)
|
980
|
+
save_variation(visitor_code, eval_exp, track: track)
|
956
981
|
end
|
957
982
|
end
|
958
983
|
Logging::KameleoonLogger.debug(
|
data/lib/kameleoon/utils.rb
CHANGED
@@ -38,6 +38,10 @@ module Kameleoon
|
|
38
38
|
calculate("#{visitor_code}#{container_id}#{suffix}")
|
39
39
|
end
|
40
40
|
|
41
|
+
def self.obtain_hash_for_me_group(visitor_code, me_group_name)
|
42
|
+
calculate("#{visitor_code}#{me_group_name}")
|
43
|
+
end
|
44
|
+
|
41
45
|
def self.calculate(string_to_hash)
|
42
46
|
parsed_value = Digest::SHA256.hexdigest(string_to_hash.encode('UTF-8')).to_i(16)
|
43
47
|
max_value = BigDecimal('2')**BigDecimal('256')
|
data/lib/kameleoon/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kameleoon-client-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kameleoon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-02-
|
11
|
+
date: 2025-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: em-http-request
|
@@ -80,6 +80,7 @@ files:
|
|
80
80
|
- lib/kameleoon/configuration/data_file.rb
|
81
81
|
- lib/kameleoon/configuration/experiment.rb
|
82
82
|
- lib/kameleoon/configuration/feature_flag.rb
|
83
|
+
- lib/kameleoon/configuration/me_group.rb
|
83
84
|
- lib/kameleoon/configuration/rule.rb
|
84
85
|
- lib/kameleoon/configuration/settings.rb
|
85
86
|
- lib/kameleoon/configuration/variable.rb
|