amplitude-experiment 1.2.5 → 1.3.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/amplitude-experiment.rb +1 -0
- data/lib/experiment/error.rb +11 -0
- data/lib/experiment/remote/client.rb +63 -9
- data/lib/experiment/variant.rb +10 -2
- data/lib/experiment/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: 5bebb227696dfbf198819fdba2640a000c67ca3a9c89d593cc03a4433ef532c8
|
4
|
+
data.tar.gz: fb79230b6409d82cf3d849f07cb1705abc22ae10a27e7bdfbbe6d1add1e100d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc2885c715208465d15a6b4217e684a2caa0eb055963b1a5ff0fcdc7829239b894d685f305383cd483fff2b082592c395672c1d75140e0537543b5479e425557
|
7
|
+
data.tar.gz: 6d1c6b2488ddc5e28d0162e3535be65c3ed3c5767e08af71acdf7933a6f42a20c3d6994638b45713c8f9a9dd20ccfe054a9323465badff1acdd6960fb5cf9376
|
data/lib/amplitude-experiment.rb
CHANGED
@@ -15,6 +15,7 @@ require 'experiment/local/assignment/assignment_service'
|
|
15
15
|
require 'experiment/local/assignment/assignment_config'
|
16
16
|
require 'experiment/util/lru_cache'
|
17
17
|
require 'experiment/util/hash'
|
18
|
+
require 'experiment/error'
|
18
19
|
|
19
20
|
# Amplitude Experiment Module
|
20
21
|
module AmplitudeExperiment
|
@@ -19,24 +19,37 @@ module AmplitudeExperiment
|
|
19
19
|
else
|
20
20
|
Logger::INFO
|
21
21
|
end
|
22
|
-
endpoint = "#{@config.server_url}/sdk/vardata"
|
22
|
+
endpoint = "#{@config.server_url}/sdk/v2/vardata?v=0"
|
23
23
|
@uri = URI(endpoint)
|
24
24
|
raise ArgumentError, 'Experiment API key is empty' if @api_key.nil? || @api_key.empty?
|
25
25
|
end
|
26
26
|
|
27
|
-
# Fetch all variants for a user
|
27
|
+
# Fetch all variants for a user synchronously.
|
28
28
|
#
|
29
29
|
# This method will automatically retry if configured (default).
|
30
30
|
# @param [User] user
|
31
31
|
# @return [Hash] Variants Hash
|
32
32
|
def fetch(user)
|
33
|
+
filter_default_variants(fetch_internal(user))
|
34
|
+
rescue StandardError => e
|
35
|
+
@logger.error("[Experiment] Failed to fetch variants: #{e.message}")
|
36
|
+
{}
|
37
|
+
end
|
38
|
+
|
39
|
+
# Fetch all variants for a user synchronously.
|
40
|
+
#
|
41
|
+
# This method will automatically retry if configured (default). This function differs from fetch as it will
|
42
|
+
# return a default variant object if the flag was evaluated but the user was not assigned (i.e. off).
|
43
|
+
# @param [User] user
|
44
|
+
# @return [Hash] Variants Hash
|
45
|
+
def fetch_v2(user)
|
33
46
|
fetch_internal(user)
|
34
47
|
rescue StandardError => e
|
35
48
|
@logger.error("[Experiment] Failed to fetch variants: #{e.message}")
|
36
49
|
{}
|
37
50
|
end
|
38
51
|
|
39
|
-
# Fetch all variants for a user
|
52
|
+
# Fetch all variants for a user asynchronously.
|
40
53
|
#
|
41
54
|
# This method will automatically retry if configured (default).
|
42
55
|
# @param [User] user
|
@@ -53,6 +66,24 @@ module AmplitudeExperiment
|
|
53
66
|
end
|
54
67
|
end
|
55
68
|
|
69
|
+
# Fetch all variants for a user asynchronously. This function differs from fetch as it will
|
70
|
+
# return a default variant object if the flag was evaluated but the user was not assigned (i.e. off).
|
71
|
+
#
|
72
|
+
# This method will automatically retry if configured (default).
|
73
|
+
# @param [User] user
|
74
|
+
# @yield [User, Hash] callback block takes user object and variants hash
|
75
|
+
def fetch_async_v2(user, &callback)
|
76
|
+
Thread.new do
|
77
|
+
variants = fetch_internal(user)
|
78
|
+
yield(user, filter_default_variants(variants)) unless callback.nil?
|
79
|
+
variants
|
80
|
+
rescue StandardError => e
|
81
|
+
@logger.error("[Experiment] Failed to fetch variants: #{e.message}")
|
82
|
+
yield(user, {}) unless callback.nil?
|
83
|
+
{}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
56
87
|
private
|
57
88
|
|
58
89
|
# @param [User] user
|
@@ -61,12 +92,14 @@ module AmplitudeExperiment
|
|
61
92
|
do_fetch(user, @config.fetch_timeout_millis)
|
62
93
|
rescue StandardError => e
|
63
94
|
@logger.error("[Experiment] Fetch failed: #{e.message}")
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
95
|
+
if should_retry_fetch?(e)
|
96
|
+
begin
|
97
|
+
retry_fetch(user)
|
98
|
+
rescue StandardError => err
|
99
|
+
@logger.error("[Experiment] Retry Fetch failed: #{err.message}")
|
100
|
+
end
|
68
101
|
end
|
69
|
-
|
102
|
+
raise e
|
70
103
|
end
|
71
104
|
|
72
105
|
# @param [User] user
|
@@ -108,6 +141,8 @@ module AmplitudeExperiment
|
|
108
141
|
end_time = Time.now
|
109
142
|
elapsed = (end_time - start_time) * 1000.0
|
110
143
|
@logger.debug("[Experiment] Fetch complete in #{elapsed.round(3)} ms")
|
144
|
+
raise FetchError.new(response.code.to_i, "Fetch error response: status=#{response.code} #{response.message}") if response.code != '200'
|
145
|
+
|
111
146
|
json = JSON.parse(response.body)
|
112
147
|
variants = parse_json_variants(json)
|
113
148
|
@logger.debug("[Experiment] Fetched variants: #{variants}")
|
@@ -128,7 +163,7 @@ module AmplitudeExperiment
|
|
128
163
|
# value was previously under the "key" field
|
129
164
|
variant_value = value.fetch('key')
|
130
165
|
end
|
131
|
-
variants.store(key, Variant.new(variant_value, value.fetch('payload', nil)))
|
166
|
+
variants.store(key, Variant.new(variant_value, value.fetch('payload', nil), value.fetch('key', nil), value.fetch('metadata', nil)))
|
132
167
|
end
|
133
168
|
variants
|
134
169
|
end
|
@@ -140,5 +175,24 @@ module AmplitudeExperiment
|
|
140
175
|
user.library = "experiment-ruby-server/#{VERSION}"
|
141
176
|
user
|
142
177
|
end
|
178
|
+
|
179
|
+
def should_retry_fetch?(err)
|
180
|
+
return err.status_code < 400 || err.status_code >= 500 || err.status_code == 429 if err.is_a?(FetchError)
|
181
|
+
|
182
|
+
true
|
183
|
+
end
|
184
|
+
|
185
|
+
def filter_default_variants(variants)
|
186
|
+
variants.each do |key, value|
|
187
|
+
default = value&.metadata&.fetch('default', nil)
|
188
|
+
deployed = value&.metadata&.fetch('deployed', nil)
|
189
|
+
default = false if default.nil?
|
190
|
+
deployed = true if deployed.nil?
|
191
|
+
variants.delete(key) if default || !deployed
|
192
|
+
end
|
193
|
+
variants
|
194
|
+
end
|
195
|
+
|
196
|
+
private :filter_default_variants
|
143
197
|
end
|
144
198
|
end
|
data/lib/experiment/variant.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
module AmplitudeExperiment
|
2
2
|
# Variant
|
3
3
|
class Variant
|
4
|
+
# The key of the variant determined by the flag configuration.
|
5
|
+
# @return [String] the value of variant key
|
6
|
+
attr_accessor :key
|
7
|
+
|
4
8
|
# The value of the variant determined by the flag configuration.
|
5
9
|
# @return [String] the value of variant value
|
6
10
|
attr_accessor :value
|
@@ -9,17 +13,21 @@ module AmplitudeExperiment
|
|
9
13
|
# @return [Object, nil] the value of variant payload
|
10
14
|
attr_accessor :payload
|
11
15
|
|
16
|
+
attr_accessor :metadata
|
17
|
+
|
12
18
|
# @param [String] value The value of the variant determined by the flag configuration.
|
13
19
|
# @param [Object, nil] payload The attached payload, if any.
|
14
|
-
def initialize(value, payload = nil)
|
20
|
+
def initialize(value, payload = nil, key = nil, metadata = nil)
|
21
|
+
@key = key
|
15
22
|
@value = value
|
16
23
|
@payload = payload
|
24
|
+
@metadata = metadata
|
17
25
|
end
|
18
26
|
|
19
27
|
# Determine if current variant equal other variant
|
20
28
|
# @param [Variant] other
|
21
29
|
def ==(other)
|
22
|
-
value == other.value &&
|
30
|
+
key == other.key && value == other.value &&
|
23
31
|
payload == other.payload
|
24
32
|
end
|
25
33
|
end
|
data/lib/experiment/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: amplitude-experiment
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amplitude
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -176,6 +176,7 @@ files:
|
|
176
176
|
- lib/amplitude/utils.rb
|
177
177
|
- lib/amplitude/workers.rb
|
178
178
|
- lib/experiment/cookie.rb
|
179
|
+
- lib/experiment/error.rb
|
179
180
|
- lib/experiment/factory.rb
|
180
181
|
- lib/experiment/local/assignment/assignment.rb
|
181
182
|
- lib/experiment/local/assignment/assignment_config.rb
|