determinator 2.4.4 → 2.5.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/CHANGELOG.md +5 -0
- data/lib/determinator.rb +1 -0
- data/lib/determinator/control.rb +34 -7
- data/lib/determinator/feature.rb +36 -6
- data/lib/determinator/fixed_determination.rb +20 -0
- data/lib/determinator/serializers/json.rb +9 -8
- data/lib/determinator/version.rb +1 -1
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b505247b6902fb3768389da7b5a20e625f95e5ccaec778ae7fb52e1808286b73
|
4
|
+
data.tar.gz: 659b93e86df258535f904bd90d91768767c5c1644cd578d3efe3f45a9c2aba6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 753968e66ac00b3f0606eed33b5d1873ad23a89cce901b69e261f38263ff14f18b975a0f03e55146e8ea78dc397b1a48878f10c3b1fc6eadd4f278a78f2a7703
|
7
|
+
data.tar.gz: 46d183bc1e87d5031b43115bb63573503725f441a44603577274fef9817cd20722471bcba1b46d018beab4828bbcbf738c4de742aff0de26578178330edd2885
|
data/CHANGELOG.md
CHANGED
data/lib/determinator.rb
CHANGED
@@ -2,6 +2,7 @@ require 'determinator/version'
|
|
2
2
|
require 'determinator/control'
|
3
3
|
require 'determinator/feature'
|
4
4
|
require 'determinator/target_group'
|
5
|
+
require 'determinator/fixed_determination'
|
5
6
|
require 'determinator/cache/fetch_wrapper'
|
6
7
|
require 'determinator/serializers/json'
|
7
8
|
require 'determinator/missing_response'
|
data/lib/determinator/control.rb
CHANGED
@@ -81,6 +81,14 @@ module Determinator
|
|
81
81
|
|
82
82
|
return feature.override_value_for(id) if feature.overridden_for?(id)
|
83
83
|
|
84
|
+
fixed_determination = choose_fixed_determination(feature, properties)
|
85
|
+
# Given constraints have specified that this actor's determination should be fixed
|
86
|
+
if fixed_determination
|
87
|
+
return false unless fixed_determination.feature_on
|
88
|
+
return true unless feature.experiment?
|
89
|
+
return fixed_determination.variant
|
90
|
+
end
|
91
|
+
|
84
92
|
target_group = choose_target_group(feature, properties)
|
85
93
|
# Given constraints have excluded this actor from this experiment
|
86
94
|
return false unless target_group
|
@@ -106,23 +114,34 @@ module Determinator
|
|
106
114
|
false
|
107
115
|
end
|
108
116
|
|
117
|
+
def choose_fixed_determination(feature, properties)
|
118
|
+
# Keys and values must be strings
|
119
|
+
normalised_properties = normalise_properties(properties)
|
120
|
+
|
121
|
+
feature.fixed_determinations.find { |fd|
|
122
|
+
matches_constraints(normalised_properties, fd.constraints)
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
109
126
|
def choose_target_group(feature, properties)
|
110
127
|
# Keys and values must be strings
|
111
|
-
normalised_properties = properties
|
112
|
-
hash[name.to_s] = [*values].map(&:to_s)
|
113
|
-
end
|
128
|
+
normalised_properties = normalise_properties(properties)
|
114
129
|
|
115
130
|
feature.target_groups.select { |tg|
|
116
131
|
next false unless tg.rollout.between?(1, 65_536)
|
117
132
|
|
118
|
-
tg.constraints
|
119
|
-
present = [*normalised_properties[scope]]
|
120
|
-
fit && matches_requirements?(scope, required, present)
|
121
|
-
end
|
133
|
+
matches_constraints(normalised_properties, tg.constraints)
|
122
134
|
# Must choose target group deterministically, if more than one match
|
123
135
|
}.sort_by { |tg| tg.rollout }.last
|
124
136
|
end
|
125
137
|
|
138
|
+
def matches_constraints(normalised_properties, constraints)
|
139
|
+
constraints.reduce(true) do |fit, (scope, *required)|
|
140
|
+
present = [*normalised_properties[scope]]
|
141
|
+
fit && matches_requirements?(scope, required, present)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
126
145
|
def matches_requirements?(scope, required, present)
|
127
146
|
case scope
|
128
147
|
when "app_version" then has_any_app_version?(required, present)
|
@@ -205,5 +224,13 @@ module Determinator
|
|
205
224
|
|
206
225
|
raise ArgumentError, "A variant should have been found by this point, there is a bug in the code."
|
207
226
|
end
|
227
|
+
|
228
|
+
private
|
229
|
+
|
230
|
+
def normalise_properties(properties)
|
231
|
+
properties.each_with_object({}) do |(name, values), hash|
|
232
|
+
hash[name.to_s] = [*values].map(&:to_s)
|
233
|
+
end
|
234
|
+
end
|
208
235
|
end
|
209
236
|
end
|
data/lib/determinator/feature.rb
CHANGED
@@ -3,13 +3,14 @@ module Determinator
|
|
3
3
|
#
|
4
4
|
# @attr_reader [nil,Hash<String,Integer>] variants The variants for this experiment, with the name of the variant as the key and the weight as the value. Will be nil for non-experiments.
|
5
5
|
class Feature
|
6
|
-
attr_reader :name, :identifier, :bucket_type, :variants, :target_groups, :active, :winning_variant
|
6
|
+
attr_reader :name, :identifier, :bucket_type, :variants, :target_groups, :fixed_determinations, :active, :winning_variant
|
7
7
|
|
8
|
-
def initialize(name:, identifier:, bucket_type:, target_groups:, variants: {}, overrides: {}, active: false, winning_variant: nil)
|
8
|
+
def initialize(name:, identifier:, bucket_type:, target_groups:, fixed_determinations: [], variants: {}, overrides: {}, active: false, winning_variant: nil)
|
9
9
|
@name = name.to_s
|
10
|
-
@identifier =
|
10
|
+
@identifier = identifier.to_s
|
11
11
|
@variants = variants
|
12
12
|
@target_groups = parse_target_groups(target_groups)
|
13
|
+
@fixed_determinations = parse_fixed_determinations(fixed_determinations)
|
13
14
|
@winning_variant = parse_outcome(winning_variant, allow_exclusion: false)
|
14
15
|
@active = active
|
15
16
|
@bucket_type = bucket_type.to_sym
|
@@ -72,14 +73,43 @@ module Determinator
|
|
72
73
|
|
73
74
|
TargetGroup.new(
|
74
75
|
rollout: target_group['rollout'].to_i,
|
75
|
-
constraints: constraints
|
76
|
-
hash[key.to_s] = [*value].map(&:to_s)
|
77
|
-
end
|
76
|
+
constraints: parse_constraints(constraints)
|
78
77
|
)
|
79
78
|
|
80
79
|
# Invalid target groups are ignored
|
81
80
|
rescue
|
82
81
|
nil
|
83
82
|
end
|
83
|
+
|
84
|
+
def parse_fixed_determinations(fixed_determinations)
|
85
|
+
fixed_determinations.map(&method(:parse_fixed_determination)).compact
|
86
|
+
end
|
87
|
+
|
88
|
+
def parse_fixed_determination(fixed_determination)
|
89
|
+
return fixed_determination if fixed_determination.is_a? FixedDetermination
|
90
|
+
|
91
|
+
variant = fixed_determination['variant']
|
92
|
+
return nil if variant && !variants.keys.include?(variant)
|
93
|
+
|
94
|
+
# if a variant is present the fixed determination should always be on
|
95
|
+
return nil if variant && !fixed_determination['feature_on']
|
96
|
+
|
97
|
+
constraints = fixed_determination['constraints'].to_h
|
98
|
+
|
99
|
+
FixedDetermination.new(
|
100
|
+
feature_on: fixed_determination['feature_on'],
|
101
|
+
variant: variant,
|
102
|
+
constraints: parse_constraints(constraints)
|
103
|
+
)
|
104
|
+
# Invalid fixed determinations are ignored
|
105
|
+
rescue
|
106
|
+
nil
|
107
|
+
end
|
108
|
+
|
109
|
+
def parse_constraints(constraints)
|
110
|
+
constraints.each_with_object({}) do |(key, value), hash|
|
111
|
+
hash[key.to_s] = [*value].map(&:to_s)
|
112
|
+
end
|
113
|
+
end
|
84
114
|
end
|
85
115
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Determinator
|
2
|
+
class FixedDetermination
|
3
|
+
attr_reader :feature_on, :variant, :constraints
|
4
|
+
|
5
|
+
def initialize(feature_on:, variant:, constraints: {})
|
6
|
+
@feature_on = feature_on
|
7
|
+
@variant = variant
|
8
|
+
@constraints = constraints
|
9
|
+
end
|
10
|
+
|
11
|
+
def inspect
|
12
|
+
"<feature_on: #{feature_on}, variant: #{variant}, constraints: #{constraints}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def ==(other)
|
16
|
+
return false unless other.is_a?(self.class)
|
17
|
+
other.feature_on == feature_on && other.variant == variant && other.constraints == constraints
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -12,14 +12,15 @@ module Determinator
|
|
12
12
|
obj = string_or_hash.is_a?(Hash) ? string_or_hash : ::JSON.parse(string_or_hash)
|
13
13
|
|
14
14
|
Determinator::Feature.new(
|
15
|
-
name:
|
16
|
-
identifier:
|
17
|
-
bucket_type:
|
18
|
-
active:
|
19
|
-
target_groups:
|
20
|
-
|
21
|
-
|
22
|
-
|
15
|
+
name: obj['name'],
|
16
|
+
identifier: obj['identifier'],
|
17
|
+
bucket_type: obj['bucket_type'],
|
18
|
+
active: (obj['active'] === true),
|
19
|
+
target_groups: obj['target_groups'],
|
20
|
+
fixed_determinations: obj['fixed_determinations'].to_a,
|
21
|
+
variants: obj['variants'].to_h,
|
22
|
+
overrides: obj['overrides'].to_h,
|
23
|
+
winning_variant: obj['winning_variant'].to_s,
|
23
24
|
)
|
24
25
|
end
|
25
26
|
end
|
data/lib/determinator/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: determinator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JP Hastings-Spital
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -150,7 +150,7 @@ dependencies:
|
|
150
150
|
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
|
-
description:
|
153
|
+
description:
|
154
154
|
email:
|
155
155
|
- jp@deliveroo.co.uk
|
156
156
|
executables: []
|
@@ -210,6 +210,7 @@ files:
|
|
210
210
|
- lib/determinator/control.rb
|
211
211
|
- lib/determinator/error_response.rb
|
212
212
|
- lib/determinator/feature.rb
|
213
|
+
- lib/determinator/fixed_determination.rb
|
213
214
|
- lib/determinator/missing_response.rb
|
214
215
|
- lib/determinator/retrieve/dynaconf.rb
|
215
216
|
- lib/determinator/retrieve/file.rb
|
@@ -231,7 +232,7 @@ homepage: https://github.com/deliveroo/determinator
|
|
231
232
|
licenses:
|
232
233
|
- MIT
|
233
234
|
metadata: {}
|
234
|
-
post_install_message:
|
235
|
+
post_install_message:
|
235
236
|
rdoc_options: []
|
236
237
|
require_paths:
|
237
238
|
- lib
|
@@ -246,8 +247,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
246
247
|
- !ruby/object:Gem::Version
|
247
248
|
version: '0'
|
248
249
|
requirements: []
|
249
|
-
rubygems_version: 3.0.
|
250
|
-
signing_key:
|
250
|
+
rubygems_version: 3.0.6
|
251
|
+
signing_key:
|
251
252
|
specification_version: 4
|
252
253
|
summary: Determine which experiments and features a specific actor should see.
|
253
254
|
test_files: []
|