amplitude-experiment 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/amplitude-experiment.gemspec +32 -0
- data/lib/amplitude-experiment.rb +0 -2
- data/lib/experiment/local/client.rb +39 -34
- data/lib/experiment/local/config.rb +1 -5
- data/lib/experiment/local/evaluation/evaluation.rb +17 -0
- data/lib/experiment/local/evaluation/lib/linuxArm64/libevaluation_interop.so +0 -0
- data/lib/experiment/local/evaluation/lib/linuxArm64/libevaluation_interop_api.h +28 -0
- data/lib/experiment/local/evaluation/lib/linuxX64/libevaluation_interop.so +0 -0
- data/lib/experiment/local/evaluation/lib/linuxX64/libevaluation_interop_api.h +28 -0
- data/lib/experiment/local/evaluation/lib/macosArm64/libevaluation_interop.dylib +0 -0
- data/lib/experiment/local/evaluation/lib/macosArm64/libevaluation_interop_api.h +28 -0
- data/lib/experiment/local/evaluation/lib/macosX64/libevaluation_interop.dylib +0 -0
- data/lib/experiment/local/evaluation/lib/macosX64/libevaluation_interop_api.h +28 -0
- data/lib/experiment/local/fetcher.rb +22 -3
- data/lib/experiment/version.rb +1 -1
- metadata +3 -4
- data/lib/experiment/local/cache.rb +0 -53
- data/lib/experiment/local/poller.rb +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff36301b51f9c519b85c5361aa6e50e45d0e55738ee6d36e10b3599e6b91b98b
|
4
|
+
data.tar.gz: 6e03119d4dd2b6f33c4f0ba312043aac2eb688f211cf827a046d90457a40dcdb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf4ab1ee2bdc9dc1d40c0b95cbb2a6f4559a7473fa64997045bbb7b0bc9ac3a5c05cc5826a3f411198e3807f41e57de9c491cf44bbe2409c02fd368174d425a5
|
7
|
+
data.tar.gz: 9fb0b7f55cde6e6e51774b5dc434c8f9ec4707b94a03576636a5bec115c23f4e60d09a93fb855595f41be65b8a9ef0b912c671587df16bbe5587950b267e3a5a
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.expand_path('lib/experiment/version', __dir__)
|
2
|
+
Gem::Specification.new do |spec|
|
3
|
+
spec.name = 'amplitude-experiment'
|
4
|
+
spec.version = AmplitudeExperiment::VERSION
|
5
|
+
spec.authors = ['Amplitude']
|
6
|
+
spec.email = ['sdk@amplitude.com']
|
7
|
+
spec.summary = 'Amplitude Experiment Ruby Server SDK'
|
8
|
+
spec.description = 'Amplitude Experiment Ruby Server SDK'
|
9
|
+
spec.homepage = 'https://github.com/amplitude/experiment-ruby-server'
|
10
|
+
spec.license = 'MIT'
|
11
|
+
spec.platform = Gem::Platform::RUBY
|
12
|
+
spec.required_ruby_version = '>= 2.0'
|
13
|
+
|
14
|
+
spec.files = Dir['README.md',
|
15
|
+
'lib/**/*.rb',
|
16
|
+
'amplitude-experiment.gemspec',
|
17
|
+
'Gemfile',
|
18
|
+
'lib/experiment/local/evaluation/lib/**/*']
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
spec.extra_rdoc_files = ['README.md']
|
21
|
+
|
22
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
23
|
+
spec.add_development_dependency 'rdoc', '= 6.4'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 3.6'
|
25
|
+
spec.add_development_dependency 'rubocop', '= 1.21'
|
26
|
+
spec.add_development_dependency 'simplecov', '~> 0.21'
|
27
|
+
spec.add_development_dependency 'webmock', '~> 3.14'
|
28
|
+
spec.add_development_dependency 'yard', '~> 0.9'
|
29
|
+
spec.add_development_dependency 'psych', '~> 4.0'
|
30
|
+
spec.metadata['rubygems_mfa_required'] = 'false'
|
31
|
+
spec.add_runtime_dependency 'ffi', '~> 1.15.5'
|
32
|
+
end
|
data/lib/amplitude-experiment.rb
CHANGED
@@ -8,9 +8,7 @@ require 'experiment/factory'
|
|
8
8
|
require 'experiment/remote/client'
|
9
9
|
require 'experiment/local/client'
|
10
10
|
require 'experiment/local/config'
|
11
|
-
require 'experiment/local/cache'
|
12
11
|
require 'experiment/local/fetcher'
|
13
|
-
require 'experiment/local/poller'
|
14
12
|
|
15
13
|
# Amplitude Experiment Module
|
16
14
|
module AmplitudeExperiment
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'uri'
|
2
2
|
require 'logger'
|
3
|
-
require 'experiment/local/evaluation/evaluation'
|
4
3
|
|
5
4
|
module AmplitudeExperiment
|
6
5
|
# Main client for fetching variant data.
|
@@ -10,9 +9,11 @@ module AmplitudeExperiment
|
|
10
9
|
# @param [String] api_key The environment API Key
|
11
10
|
# @param [LocalEvaluationConfig] config The config object
|
12
11
|
def initialize(api_key, config = nil)
|
12
|
+
require 'experiment/local/evaluation/evaluation'
|
13
13
|
@api_key = api_key
|
14
14
|
@config = config || LocalEvaluationConfig.new
|
15
|
-
@
|
15
|
+
@flags = nil
|
16
|
+
@flags_mutex = Mutex.new
|
16
17
|
@logger = Logger.new($stdout)
|
17
18
|
@logger.level = if @config.debug
|
18
19
|
Logger::DEBUG
|
@@ -20,8 +21,6 @@ module AmplitudeExperiment
|
|
20
21
|
Logger::INFO
|
21
22
|
end
|
22
23
|
@fetcher = LocalEvaluationFetcher.new(api_key, @config.debug, @config.server_url)
|
23
|
-
@poller = FlagConfigPoller.new(@fetcher, @cache, @config.debug, @config.flag_config_polling_interval_millis)
|
24
|
-
|
25
24
|
raise ArgumentError, 'Experiment API key is empty' if @api_key.nil? || @api_key.empty?
|
26
25
|
end
|
27
26
|
|
@@ -32,53 +31,59 @@ module AmplitudeExperiment
|
|
32
31
|
#
|
33
32
|
# @return [Hash[String, Variant]] The evaluated variants
|
34
33
|
def evaluate(user, flag_keys = [])
|
35
|
-
|
36
|
-
|
37
|
-
@cache.cache.each do |_, value|
|
38
|
-
flag_configs.push(value)
|
39
|
-
end
|
40
|
-
else
|
41
|
-
flag_configs = get_flag_configs(flag_keys)
|
34
|
+
flags = @flags_mutex.synchronize do
|
35
|
+
@flags
|
42
36
|
end
|
43
|
-
|
44
|
-
user_str = user.to_json
|
45
|
-
@logger.debug("[Experiment] Evaluate: User: #{user_str} - Rules: #{flag_configs_str}") if @config.debug
|
46
|
-
result_json = evaluation(flag_configs_str, user_str)
|
47
|
-
@logger.debug("[Experiment] evaluate - result: #{variants}") if @config.debug
|
48
|
-
result = JSON.parse(result_json)
|
49
|
-
variants = {}
|
50
|
-
result.each do |key, value|
|
51
|
-
next if value['isDefaultVariant']
|
37
|
+
return {} if flags.nil?
|
52
38
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
39
|
+
user_str = user.to_json
|
40
|
+
@logger.debug("[Experiment] Evaluate: User: #{user_str} - Rules: #{flags}") if @config.debug
|
41
|
+
results_json = evaluation(flags, user_str)
|
42
|
+
@logger.debug("[Experiment] evaluate - result: #{results_json}") if @config.debug
|
43
|
+
parse_results_json(results_json, flag_keys)
|
58
44
|
end
|
59
45
|
|
60
46
|
# Fetch initial flag configurations and start polling for updates.
|
61
47
|
# You must call this function to begin polling for flag config updates.
|
62
48
|
def start
|
63
|
-
@
|
49
|
+
return if @is_running
|
50
|
+
|
51
|
+
@logger.debug('[Experiment] poller - start') if @debug
|
52
|
+
run
|
64
53
|
end
|
65
54
|
|
66
55
|
# Stop polling for flag configurations. Close resource like connection pool with client
|
67
56
|
def stop
|
68
|
-
@
|
57
|
+
@poller_thread&.exit
|
58
|
+
@is_running = false
|
59
|
+
@poller_thread = nil
|
69
60
|
end
|
70
61
|
|
71
62
|
private
|
72
63
|
|
73
|
-
def
|
74
|
-
|
64
|
+
def parse_results_json(results_json, flag_keys)
|
65
|
+
result = JSON.parse(results_json)
|
66
|
+
variants = {}
|
67
|
+
result.each do |key, value|
|
68
|
+
next if value['isDefaultVariant'] || (flag_keys.empty? && flag_keys.include?(key))
|
69
|
+
|
70
|
+
variant_key = value['variant']['key']
|
71
|
+
variant_payload = value['variant']['payload']
|
72
|
+
variants.store(key, Variant.new(variant_key, variant_payload))
|
73
|
+
end
|
74
|
+
variants
|
75
|
+
end
|
75
76
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
def run
|
78
|
+
@is_running = true
|
79
|
+
flags = @fetcher.fetch_v1
|
80
|
+
@flags_mutex.synchronize do
|
81
|
+
@flags = flags
|
82
|
+
end
|
83
|
+
@poller_thread = Thread.new do
|
84
|
+
sleep(@config.flag_config_polling_interval_millis / 1000.to_f)
|
85
|
+
run
|
80
86
|
end
|
81
|
-
flag_configs
|
82
87
|
end
|
83
88
|
end
|
84
89
|
end
|
@@ -12,11 +12,7 @@ module AmplitudeExperiment
|
|
12
12
|
# @return [String] the value of server url
|
13
13
|
attr_accessor :server_url
|
14
14
|
|
15
|
-
# The
|
16
|
-
# @return [Hash] the value of bootstrap
|
17
|
-
attr_accessor :bootstrap
|
18
|
-
|
19
|
-
# The server endpoint from which to request variants.
|
15
|
+
# The polling interval for flag configs.
|
20
16
|
# @return [long] the value of flag config polling interval in million seconds
|
21
17
|
attr_accessor :flag_config_polling_interval_millis
|
22
18
|
|
@@ -25,14 +25,31 @@ module EvaluationInterop
|
|
25
25
|
:DisposeString, callback([:string], :void),
|
26
26
|
:IsInstance, callback([:pointer, :string], :pointer),
|
27
27
|
:createNullableByte, callback([:string], :pointer),
|
28
|
+
:getNonNullValueOfByte, callback([:pointer], :pointer),
|
28
29
|
:createNullableShort, callback([:pointer], :pointer),
|
30
|
+
:getNonNullValueOfShort, callback([:pointer], :pointer),
|
29
31
|
:createNullableInt, callback([:pointer], :pointer),
|
32
|
+
:getNonNullValueOfInt, callback([:pointer], :pointer),
|
30
33
|
:createNullableLong, callback([:pointer], :pointer),
|
34
|
+
:getNonNullValueOfLong, callback([:pointer], :pointer),
|
31
35
|
:createNullableFloat, callback([:pointer], :pointer),
|
36
|
+
:getNonNullValueOfFloat, callback([:pointer], :pointer),
|
32
37
|
:createNullableDouble, callback([:pointer], :pointer),
|
38
|
+
:getNonNullValueOfDouble, callback([:pointer], :pointer),
|
33
39
|
:createNullableChar, callback([:pointer], :pointer),
|
40
|
+
:getNonNullValueOfChar, callback([:pointer], :pointer),
|
34
41
|
:createNullableBoolean, callback([:pointer], :pointer),
|
42
|
+
:getNonNullValueOfBoolean, callback([:pointer], :pointer),
|
35
43
|
:createNullableUnit, callback([], :pointer),
|
44
|
+
:createNullableUByte, callback([:pointer], :pointer),
|
45
|
+
:getNonNullValueOfUByte, callback([:pointer], :pointer),
|
46
|
+
:createNullableUShort, callback([:pointer], :pointer),
|
47
|
+
:getNonNullValueOfUShort, callback([:pointer], :pointer),
|
48
|
+
:createNullableUInt, callback([:pointer], :pointer),
|
49
|
+
:getNonNullValueOfUInt, callback([:pointer], :pointer),
|
50
|
+
:createNullableULong, callback([:pointer], :pointer),
|
51
|
+
:getNonNullValueOfULong, callback([:pointer], :pointer),
|
52
|
+
|
36
53
|
:kotlin, Kotlin
|
37
54
|
end
|
38
55
|
|
Binary file
|
@@ -51,6 +51,18 @@ typedef struct {
|
|
51
51
|
typedef struct {
|
52
52
|
libevaluation_interop_KNativePtr pinned;
|
53
53
|
} libevaluation_interop_kref_kotlin_Unit;
|
54
|
+
typedef struct {
|
55
|
+
libevaluation_interop_KNativePtr pinned;
|
56
|
+
} libevaluation_interop_kref_kotlin_UByte;
|
57
|
+
typedef struct {
|
58
|
+
libevaluation_interop_KNativePtr pinned;
|
59
|
+
} libevaluation_interop_kref_kotlin_UShort;
|
60
|
+
typedef struct {
|
61
|
+
libevaluation_interop_KNativePtr pinned;
|
62
|
+
} libevaluation_interop_kref_kotlin_UInt;
|
63
|
+
typedef struct {
|
64
|
+
libevaluation_interop_KNativePtr pinned;
|
65
|
+
} libevaluation_interop_kref_kotlin_ULong;
|
54
66
|
|
55
67
|
|
56
68
|
typedef struct {
|
@@ -59,14 +71,30 @@ typedef struct {
|
|
59
71
|
void (*DisposeString)(const char* string);
|
60
72
|
libevaluation_interop_KBoolean (*IsInstance)(libevaluation_interop_KNativePtr ref, const libevaluation_interop_KType* type);
|
61
73
|
libevaluation_interop_kref_kotlin_Byte (*createNullableByte)(libevaluation_interop_KByte);
|
74
|
+
libevaluation_interop_KByte (*getNonNullValueOfByte)(libevaluation_interop_kref_kotlin_Byte);
|
62
75
|
libevaluation_interop_kref_kotlin_Short (*createNullableShort)(libevaluation_interop_KShort);
|
76
|
+
libevaluation_interop_KShort (*getNonNullValueOfShort)(libevaluation_interop_kref_kotlin_Short);
|
63
77
|
libevaluation_interop_kref_kotlin_Int (*createNullableInt)(libevaluation_interop_KInt);
|
78
|
+
libevaluation_interop_KInt (*getNonNullValueOfInt)(libevaluation_interop_kref_kotlin_Int);
|
64
79
|
libevaluation_interop_kref_kotlin_Long (*createNullableLong)(libevaluation_interop_KLong);
|
80
|
+
libevaluation_interop_KLong (*getNonNullValueOfLong)(libevaluation_interop_kref_kotlin_Long);
|
65
81
|
libevaluation_interop_kref_kotlin_Float (*createNullableFloat)(libevaluation_interop_KFloat);
|
82
|
+
libevaluation_interop_KFloat (*getNonNullValueOfFloat)(libevaluation_interop_kref_kotlin_Float);
|
66
83
|
libevaluation_interop_kref_kotlin_Double (*createNullableDouble)(libevaluation_interop_KDouble);
|
84
|
+
libevaluation_interop_KDouble (*getNonNullValueOfDouble)(libevaluation_interop_kref_kotlin_Double);
|
67
85
|
libevaluation_interop_kref_kotlin_Char (*createNullableChar)(libevaluation_interop_KChar);
|
86
|
+
libevaluation_interop_KChar (*getNonNullValueOfChar)(libevaluation_interop_kref_kotlin_Char);
|
68
87
|
libevaluation_interop_kref_kotlin_Boolean (*createNullableBoolean)(libevaluation_interop_KBoolean);
|
88
|
+
libevaluation_interop_KBoolean (*getNonNullValueOfBoolean)(libevaluation_interop_kref_kotlin_Boolean);
|
69
89
|
libevaluation_interop_kref_kotlin_Unit (*createNullableUnit)(void);
|
90
|
+
libevaluation_interop_kref_kotlin_UByte (*createNullableUByte)(libevaluation_interop_KUByte);
|
91
|
+
libevaluation_interop_KUByte (*getNonNullValueOfUByte)(libevaluation_interop_kref_kotlin_UByte);
|
92
|
+
libevaluation_interop_kref_kotlin_UShort (*createNullableUShort)(libevaluation_interop_KUShort);
|
93
|
+
libevaluation_interop_KUShort (*getNonNullValueOfUShort)(libevaluation_interop_kref_kotlin_UShort);
|
94
|
+
libevaluation_interop_kref_kotlin_UInt (*createNullableUInt)(libevaluation_interop_KUInt);
|
95
|
+
libevaluation_interop_KUInt (*getNonNullValueOfUInt)(libevaluation_interop_kref_kotlin_UInt);
|
96
|
+
libevaluation_interop_kref_kotlin_ULong (*createNullableULong)(libevaluation_interop_KULong);
|
97
|
+
libevaluation_interop_KULong (*getNonNullValueOfULong)(libevaluation_interop_kref_kotlin_ULong);
|
70
98
|
|
71
99
|
/* User functions. */
|
72
100
|
struct {
|
Binary file
|
@@ -51,6 +51,18 @@ typedef struct {
|
|
51
51
|
typedef struct {
|
52
52
|
libevaluation_interop_KNativePtr pinned;
|
53
53
|
} libevaluation_interop_kref_kotlin_Unit;
|
54
|
+
typedef struct {
|
55
|
+
libevaluation_interop_KNativePtr pinned;
|
56
|
+
} libevaluation_interop_kref_kotlin_UByte;
|
57
|
+
typedef struct {
|
58
|
+
libevaluation_interop_KNativePtr pinned;
|
59
|
+
} libevaluation_interop_kref_kotlin_UShort;
|
60
|
+
typedef struct {
|
61
|
+
libevaluation_interop_KNativePtr pinned;
|
62
|
+
} libevaluation_interop_kref_kotlin_UInt;
|
63
|
+
typedef struct {
|
64
|
+
libevaluation_interop_KNativePtr pinned;
|
65
|
+
} libevaluation_interop_kref_kotlin_ULong;
|
54
66
|
|
55
67
|
|
56
68
|
typedef struct {
|
@@ -59,14 +71,30 @@ typedef struct {
|
|
59
71
|
void (*DisposeString)(const char* string);
|
60
72
|
libevaluation_interop_KBoolean (*IsInstance)(libevaluation_interop_KNativePtr ref, const libevaluation_interop_KType* type);
|
61
73
|
libevaluation_interop_kref_kotlin_Byte (*createNullableByte)(libevaluation_interop_KByte);
|
74
|
+
libevaluation_interop_KByte (*getNonNullValueOfByte)(libevaluation_interop_kref_kotlin_Byte);
|
62
75
|
libevaluation_interop_kref_kotlin_Short (*createNullableShort)(libevaluation_interop_KShort);
|
76
|
+
libevaluation_interop_KShort (*getNonNullValueOfShort)(libevaluation_interop_kref_kotlin_Short);
|
63
77
|
libevaluation_interop_kref_kotlin_Int (*createNullableInt)(libevaluation_interop_KInt);
|
78
|
+
libevaluation_interop_KInt (*getNonNullValueOfInt)(libevaluation_interop_kref_kotlin_Int);
|
64
79
|
libevaluation_interop_kref_kotlin_Long (*createNullableLong)(libevaluation_interop_KLong);
|
80
|
+
libevaluation_interop_KLong (*getNonNullValueOfLong)(libevaluation_interop_kref_kotlin_Long);
|
65
81
|
libevaluation_interop_kref_kotlin_Float (*createNullableFloat)(libevaluation_interop_KFloat);
|
82
|
+
libevaluation_interop_KFloat (*getNonNullValueOfFloat)(libevaluation_interop_kref_kotlin_Float);
|
66
83
|
libevaluation_interop_kref_kotlin_Double (*createNullableDouble)(libevaluation_interop_KDouble);
|
84
|
+
libevaluation_interop_KDouble (*getNonNullValueOfDouble)(libevaluation_interop_kref_kotlin_Double);
|
67
85
|
libevaluation_interop_kref_kotlin_Char (*createNullableChar)(libevaluation_interop_KChar);
|
86
|
+
libevaluation_interop_KChar (*getNonNullValueOfChar)(libevaluation_interop_kref_kotlin_Char);
|
68
87
|
libevaluation_interop_kref_kotlin_Boolean (*createNullableBoolean)(libevaluation_interop_KBoolean);
|
88
|
+
libevaluation_interop_KBoolean (*getNonNullValueOfBoolean)(libevaluation_interop_kref_kotlin_Boolean);
|
69
89
|
libevaluation_interop_kref_kotlin_Unit (*createNullableUnit)(void);
|
90
|
+
libevaluation_interop_kref_kotlin_UByte (*createNullableUByte)(libevaluation_interop_KUByte);
|
91
|
+
libevaluation_interop_KUByte (*getNonNullValueOfUByte)(libevaluation_interop_kref_kotlin_UByte);
|
92
|
+
libevaluation_interop_kref_kotlin_UShort (*createNullableUShort)(libevaluation_interop_KUShort);
|
93
|
+
libevaluation_interop_KUShort (*getNonNullValueOfUShort)(libevaluation_interop_kref_kotlin_UShort);
|
94
|
+
libevaluation_interop_kref_kotlin_UInt (*createNullableUInt)(libevaluation_interop_KUInt);
|
95
|
+
libevaluation_interop_KUInt (*getNonNullValueOfUInt)(libevaluation_interop_kref_kotlin_UInt);
|
96
|
+
libevaluation_interop_kref_kotlin_ULong (*createNullableULong)(libevaluation_interop_KULong);
|
97
|
+
libevaluation_interop_KULong (*getNonNullValueOfULong)(libevaluation_interop_kref_kotlin_ULong);
|
70
98
|
|
71
99
|
/* User functions. */
|
72
100
|
struct {
|
Binary file
|
@@ -51,6 +51,18 @@ typedef struct {
|
|
51
51
|
typedef struct {
|
52
52
|
libevaluation_interop_KNativePtr pinned;
|
53
53
|
} libevaluation_interop_kref_kotlin_Unit;
|
54
|
+
typedef struct {
|
55
|
+
libevaluation_interop_KNativePtr pinned;
|
56
|
+
} libevaluation_interop_kref_kotlin_UByte;
|
57
|
+
typedef struct {
|
58
|
+
libevaluation_interop_KNativePtr pinned;
|
59
|
+
} libevaluation_interop_kref_kotlin_UShort;
|
60
|
+
typedef struct {
|
61
|
+
libevaluation_interop_KNativePtr pinned;
|
62
|
+
} libevaluation_interop_kref_kotlin_UInt;
|
63
|
+
typedef struct {
|
64
|
+
libevaluation_interop_KNativePtr pinned;
|
65
|
+
} libevaluation_interop_kref_kotlin_ULong;
|
54
66
|
|
55
67
|
|
56
68
|
typedef struct {
|
@@ -59,14 +71,30 @@ typedef struct {
|
|
59
71
|
void (*DisposeString)(const char* string);
|
60
72
|
libevaluation_interop_KBoolean (*IsInstance)(libevaluation_interop_KNativePtr ref, const libevaluation_interop_KType* type);
|
61
73
|
libevaluation_interop_kref_kotlin_Byte (*createNullableByte)(libevaluation_interop_KByte);
|
74
|
+
libevaluation_interop_KByte (*getNonNullValueOfByte)(libevaluation_interop_kref_kotlin_Byte);
|
62
75
|
libevaluation_interop_kref_kotlin_Short (*createNullableShort)(libevaluation_interop_KShort);
|
76
|
+
libevaluation_interop_KShort (*getNonNullValueOfShort)(libevaluation_interop_kref_kotlin_Short);
|
63
77
|
libevaluation_interop_kref_kotlin_Int (*createNullableInt)(libevaluation_interop_KInt);
|
78
|
+
libevaluation_interop_KInt (*getNonNullValueOfInt)(libevaluation_interop_kref_kotlin_Int);
|
64
79
|
libevaluation_interop_kref_kotlin_Long (*createNullableLong)(libevaluation_interop_KLong);
|
80
|
+
libevaluation_interop_KLong (*getNonNullValueOfLong)(libevaluation_interop_kref_kotlin_Long);
|
65
81
|
libevaluation_interop_kref_kotlin_Float (*createNullableFloat)(libevaluation_interop_KFloat);
|
82
|
+
libevaluation_interop_KFloat (*getNonNullValueOfFloat)(libevaluation_interop_kref_kotlin_Float);
|
66
83
|
libevaluation_interop_kref_kotlin_Double (*createNullableDouble)(libevaluation_interop_KDouble);
|
84
|
+
libevaluation_interop_KDouble (*getNonNullValueOfDouble)(libevaluation_interop_kref_kotlin_Double);
|
67
85
|
libevaluation_interop_kref_kotlin_Char (*createNullableChar)(libevaluation_interop_KChar);
|
86
|
+
libevaluation_interop_KChar (*getNonNullValueOfChar)(libevaluation_interop_kref_kotlin_Char);
|
68
87
|
libevaluation_interop_kref_kotlin_Boolean (*createNullableBoolean)(libevaluation_interop_KBoolean);
|
88
|
+
libevaluation_interop_KBoolean (*getNonNullValueOfBoolean)(libevaluation_interop_kref_kotlin_Boolean);
|
69
89
|
libevaluation_interop_kref_kotlin_Unit (*createNullableUnit)(void);
|
90
|
+
libevaluation_interop_kref_kotlin_UByte (*createNullableUByte)(libevaluation_interop_KUByte);
|
91
|
+
libevaluation_interop_KUByte (*getNonNullValueOfUByte)(libevaluation_interop_kref_kotlin_UByte);
|
92
|
+
libevaluation_interop_kref_kotlin_UShort (*createNullableUShort)(libevaluation_interop_KUShort);
|
93
|
+
libevaluation_interop_KUShort (*getNonNullValueOfUShort)(libevaluation_interop_kref_kotlin_UShort);
|
94
|
+
libevaluation_interop_kref_kotlin_UInt (*createNullableUInt)(libevaluation_interop_KUInt);
|
95
|
+
libevaluation_interop_KUInt (*getNonNullValueOfUInt)(libevaluation_interop_kref_kotlin_UInt);
|
96
|
+
libevaluation_interop_kref_kotlin_ULong (*createNullableULong)(libevaluation_interop_KULong);
|
97
|
+
libevaluation_interop_KULong (*getNonNullValueOfULong)(libevaluation_interop_kref_kotlin_ULong);
|
70
98
|
|
71
99
|
/* User functions. */
|
72
100
|
struct {
|
Binary file
|
@@ -51,6 +51,18 @@ typedef struct {
|
|
51
51
|
typedef struct {
|
52
52
|
libevaluation_interop_KNativePtr pinned;
|
53
53
|
} libevaluation_interop_kref_kotlin_Unit;
|
54
|
+
typedef struct {
|
55
|
+
libevaluation_interop_KNativePtr pinned;
|
56
|
+
} libevaluation_interop_kref_kotlin_UByte;
|
57
|
+
typedef struct {
|
58
|
+
libevaluation_interop_KNativePtr pinned;
|
59
|
+
} libevaluation_interop_kref_kotlin_UShort;
|
60
|
+
typedef struct {
|
61
|
+
libevaluation_interop_KNativePtr pinned;
|
62
|
+
} libevaluation_interop_kref_kotlin_UInt;
|
63
|
+
typedef struct {
|
64
|
+
libevaluation_interop_KNativePtr pinned;
|
65
|
+
} libevaluation_interop_kref_kotlin_ULong;
|
54
66
|
|
55
67
|
|
56
68
|
typedef struct {
|
@@ -59,14 +71,30 @@ typedef struct {
|
|
59
71
|
void (*DisposeString)(const char* string);
|
60
72
|
libevaluation_interop_KBoolean (*IsInstance)(libevaluation_interop_KNativePtr ref, const libevaluation_interop_KType* type);
|
61
73
|
libevaluation_interop_kref_kotlin_Byte (*createNullableByte)(libevaluation_interop_KByte);
|
74
|
+
libevaluation_interop_KByte (*getNonNullValueOfByte)(libevaluation_interop_kref_kotlin_Byte);
|
62
75
|
libevaluation_interop_kref_kotlin_Short (*createNullableShort)(libevaluation_interop_KShort);
|
76
|
+
libevaluation_interop_KShort (*getNonNullValueOfShort)(libevaluation_interop_kref_kotlin_Short);
|
63
77
|
libevaluation_interop_kref_kotlin_Int (*createNullableInt)(libevaluation_interop_KInt);
|
78
|
+
libevaluation_interop_KInt (*getNonNullValueOfInt)(libevaluation_interop_kref_kotlin_Int);
|
64
79
|
libevaluation_interop_kref_kotlin_Long (*createNullableLong)(libevaluation_interop_KLong);
|
80
|
+
libevaluation_interop_KLong (*getNonNullValueOfLong)(libevaluation_interop_kref_kotlin_Long);
|
65
81
|
libevaluation_interop_kref_kotlin_Float (*createNullableFloat)(libevaluation_interop_KFloat);
|
82
|
+
libevaluation_interop_KFloat (*getNonNullValueOfFloat)(libevaluation_interop_kref_kotlin_Float);
|
66
83
|
libevaluation_interop_kref_kotlin_Double (*createNullableDouble)(libevaluation_interop_KDouble);
|
84
|
+
libevaluation_interop_KDouble (*getNonNullValueOfDouble)(libevaluation_interop_kref_kotlin_Double);
|
67
85
|
libevaluation_interop_kref_kotlin_Char (*createNullableChar)(libevaluation_interop_KChar);
|
86
|
+
libevaluation_interop_KChar (*getNonNullValueOfChar)(libevaluation_interop_kref_kotlin_Char);
|
68
87
|
libevaluation_interop_kref_kotlin_Boolean (*createNullableBoolean)(libevaluation_interop_KBoolean);
|
88
|
+
libevaluation_interop_KBoolean (*getNonNullValueOfBoolean)(libevaluation_interop_kref_kotlin_Boolean);
|
69
89
|
libevaluation_interop_kref_kotlin_Unit (*createNullableUnit)(void);
|
90
|
+
libevaluation_interop_kref_kotlin_UByte (*createNullableUByte)(libevaluation_interop_KUByte);
|
91
|
+
libevaluation_interop_KUByte (*getNonNullValueOfUByte)(libevaluation_interop_kref_kotlin_UByte);
|
92
|
+
libevaluation_interop_kref_kotlin_UShort (*createNullableUShort)(libevaluation_interop_KUShort);
|
93
|
+
libevaluation_interop_KUShort (*getNonNullValueOfUShort)(libevaluation_interop_kref_kotlin_UShort);
|
94
|
+
libevaluation_interop_kref_kotlin_UInt (*createNullableUInt)(libevaluation_interop_KUInt);
|
95
|
+
libevaluation_interop_KUInt (*getNonNullValueOfUInt)(libevaluation_interop_kref_kotlin_UInt);
|
96
|
+
libevaluation_interop_kref_kotlin_ULong (*createNullableULong)(libevaluation_interop_KULong);
|
97
|
+
libevaluation_interop_KULong (*getNonNullValueOfULong)(libevaluation_interop_kref_kotlin_ULong);
|
70
98
|
|
71
99
|
/* User functions. */
|
72
100
|
struct {
|
@@ -7,9 +7,28 @@ module AmplitudeExperiment
|
|
7
7
|
|
8
8
|
def initialize(api_key, debug, server_url = 'https://api.lab.amplitude.com')
|
9
9
|
@api_key = api_key
|
10
|
-
@
|
10
|
+
@server_url = server_url
|
11
11
|
@debug = debug
|
12
|
-
@http = PersistentHttpClient.get(
|
12
|
+
@http = PersistentHttpClient.get(server_url, { read_timeout: FLAG_CONFIG_TIMEOUT })
|
13
|
+
end
|
14
|
+
|
15
|
+
# Fetch local evaluation mode flag configs from the Experiment API server.
|
16
|
+
# These flag configs can be used to perform local evaluation.
|
17
|
+
#
|
18
|
+
# @return [String] The flag configs
|
19
|
+
def fetch_v1
|
20
|
+
# fetch flag_configs
|
21
|
+
headers = {
|
22
|
+
'Authorization' => "Api-Key #{@api_key}",
|
23
|
+
'Content-Type' => 'application/json;charset=utf-8',
|
24
|
+
'X-Amp-Exp-Library' => "experiment-ruby-server/#{VERSION}"
|
25
|
+
}
|
26
|
+
request = Net::HTTP::Get.new("#{@server_url}/sdk/v1/flags", headers)
|
27
|
+
response = @http.request(request)
|
28
|
+
raise "flagConfigs - received error response: #{response.code}: #{response.body}" unless response.is_a?(Net::HTTPOK)
|
29
|
+
|
30
|
+
@logger.debug("[Experiment] Fetch flag configs: #{response.body}") if @debug
|
31
|
+
response.body
|
13
32
|
end
|
14
33
|
|
15
34
|
# Fetch local evaluation mode flag configs from the Experiment API server.
|
@@ -23,7 +42,7 @@ module AmplitudeExperiment
|
|
23
42
|
'Content-Type' => 'application/json;charset=utf-8',
|
24
43
|
'X-Amp-Exp-Library' => "experiment-ruby-server/#{VERSION}"
|
25
44
|
}
|
26
|
-
request = Net::HTTP::Get.new(@
|
45
|
+
request = Net::HTTP::Get.new("#{@server_url}/sdk/rules?eval_mode=local", headers)
|
27
46
|
response = @http.request(request)
|
28
47
|
raise "flagConfigs - received error response: #{response.code}: #{response.body}" unless response.is_a?(Net::HTTPOK)
|
29
48
|
|
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.0
|
4
|
+
version: 1.1.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: 2023-03-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -146,10 +146,10 @@ extra_rdoc_files:
|
|
146
146
|
files:
|
147
147
|
- Gemfile
|
148
148
|
- README.md
|
149
|
+
- amplitude-experiment.gemspec
|
149
150
|
- lib/amplitude-experiment.rb
|
150
151
|
- lib/experiment/cookie.rb
|
151
152
|
- lib/experiment/factory.rb
|
152
|
-
- lib/experiment/local/cache.rb
|
153
153
|
- lib/experiment/local/client.rb
|
154
154
|
- lib/experiment/local/config.rb
|
155
155
|
- lib/experiment/local/evaluation/evaluation.rb
|
@@ -162,7 +162,6 @@ files:
|
|
162
162
|
- lib/experiment/local/evaluation/lib/macosX64/libevaluation_interop.dylib
|
163
163
|
- lib/experiment/local/evaluation/lib/macosX64/libevaluation_interop_api.h
|
164
164
|
- lib/experiment/local/fetcher.rb
|
165
|
-
- lib/experiment/local/poller.rb
|
166
165
|
- lib/experiment/persistent_http_client.rb
|
167
166
|
- lib/experiment/remote/client.rb
|
168
167
|
- lib/experiment/remote/config.rb
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'uri'
|
2
|
-
require 'logger'
|
3
|
-
|
4
|
-
module AmplitudeExperiment
|
5
|
-
# InMemoryFlagConfigCache
|
6
|
-
# The place to store the flag configs fetched from the server
|
7
|
-
class InMemoryFlagConfigCache
|
8
|
-
attr_accessor :cache
|
9
|
-
|
10
|
-
def initialize(flag_configs = {})
|
11
|
-
@semaphore = Mutex.new
|
12
|
-
@cache = flag_configs
|
13
|
-
end
|
14
|
-
|
15
|
-
def get(flag_key)
|
16
|
-
@semaphore.synchronize do
|
17
|
-
@cache.fetch(flag_key, nil)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def caches
|
22
|
-
@semaphore.synchronize do
|
23
|
-
@cache
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def put(flag_key, flag_config)
|
28
|
-
@semaphore.synchronize do
|
29
|
-
@cache.store(flag_key, flag_config.clone)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def put_all(flag_configs)
|
34
|
-
@semaphore.synchronize do
|
35
|
-
flag_configs.each do |key, value|
|
36
|
-
@cache.store(key, value.clone) if value
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def delete(flag_key)
|
42
|
-
@semaphore.synchronize do
|
43
|
-
@cache.delete(flag_key)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def clear
|
48
|
-
@semaphore.synchronize do
|
49
|
-
@cache = {}
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
module AmplitudeExperiment
|
2
|
-
# FlagConfigPoller
|
3
|
-
# update the flag_config cache value
|
4
|
-
class FlagConfigPoller
|
5
|
-
FLAG_CONFIG_POLLING_INTERVAL_MILLIS = 30_000
|
6
|
-
|
7
|
-
def initialize(fetcher, cache, debug, poll_interval_millis = FLAG_CONFIG_POLLING_INTERVAL_MILLIS)
|
8
|
-
@fetcher = fetcher
|
9
|
-
@cache = cache
|
10
|
-
@poll_interval_millis = poll_interval_millis
|
11
|
-
@logger = Logger.new($stdout)
|
12
|
-
@debug = debug
|
13
|
-
@poller_thread = nil
|
14
|
-
@is_running = false
|
15
|
-
end
|
16
|
-
|
17
|
-
# Fetch initial flag configurations and start polling for updates.
|
18
|
-
# You must call this function to begin polling for flag config updates.
|
19
|
-
# Calling this function while the poller is already running does nothing.
|
20
|
-
def start
|
21
|
-
return if @is_running
|
22
|
-
|
23
|
-
@logger.debug('[Experiment] poller - start') if @debug
|
24
|
-
run
|
25
|
-
end
|
26
|
-
|
27
|
-
# Stop polling for flag configurations.
|
28
|
-
# Calling this function while the poller is not running will do nothing.
|
29
|
-
def stop
|
30
|
-
@poller_thread&.exit
|
31
|
-
@is_running = false
|
32
|
-
@poller_thread = nil
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def run
|
38
|
-
@is_running = true
|
39
|
-
flag_configs = @fetcher.fetch
|
40
|
-
@cache.clear
|
41
|
-
@cache.put_all(flag_configs)
|
42
|
-
@poller_thread = Thread.new do
|
43
|
-
sleep(@poll_interval_millis / 1000.to_f)
|
44
|
-
run
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|