amplitude-experiment 1.0.2 → 1.1.1
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 +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 +25 -6
- data/lib/experiment/version.rb +1 -1
- metadata +2 -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: 1f1a1506a90fa83f40415c6524e7f298ed5173128ff646e11e414f108c8e2f17
|
4
|
+
data.tar.gz: 869a2a9b4f6ff51d0bacf68539e2840d6d229dba821c04419edfe90e383cf638
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb65907db678517994db78e505f511a9b1d757fe1a9da95a7aa1455e1aae3b830494be51b3b72076fc90d57654f33756c146efd5385a98c79e5b50944962c102
|
7
|
+
data.tar.gz: b85101341b8edf212426689aaf23a2ebbed40fc17ab76ca419add6714c6c2a1019438fb05f203ed49037b0552e5e4b1b99cf433ed5ff655e567ffea84915b478
|
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
|
@@ -12,16 +12,15 @@ module AmplitudeExperiment
|
|
12
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
|
19
20
|
else
|
20
21
|
Logger::INFO
|
21
22
|
end
|
22
|
-
@fetcher = LocalEvaluationFetcher.new(api_key, @
|
23
|
-
@poller = FlagConfigPoller.new(@fetcher, @cache, @config.debug, @config.flag_config_polling_interval_millis)
|
24
|
-
|
23
|
+
@fetcher = LocalEvaluationFetcher.new(api_key, @logger, @config.server_url)
|
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 {
|
@@ -5,11 +5,30 @@ module AmplitudeExperiment
|
|
5
5
|
class LocalEvaluationFetcher
|
6
6
|
FLAG_CONFIG_TIMEOUT = 5000
|
7
7
|
|
8
|
-
def initialize(api_key,
|
8
|
+
def initialize(api_key, logger, server_url = 'https://api.lab.amplitude.com')
|
9
9
|
@api_key = api_key
|
10
|
-
@
|
11
|
-
@
|
12
|
-
@http =
|
10
|
+
@server_url = server_url
|
11
|
+
@logger = logger
|
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}")
|
31
|
+
response.body
|
13
32
|
end
|
14
33
|
|
15
34
|
# Fetch local evaluation mode flag configs from the Experiment API server.
|
@@ -23,12 +42,12 @@ 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
|
|
30
49
|
flag_configs = parse(response.body)
|
31
|
-
@logger.debug("[Experiment] Fetch flag configs: #{request.body}")
|
50
|
+
@logger.debug("[Experiment] Fetch flag configs: #{request.body}")
|
32
51
|
flag_configs
|
33
52
|
end
|
34
53
|
|
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.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amplitude
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -150,7 +150,6 @@ files:
|
|
150
150
|
- lib/amplitude-experiment.rb
|
151
151
|
- lib/experiment/cookie.rb
|
152
152
|
- lib/experiment/factory.rb
|
153
|
-
- lib/experiment/local/cache.rb
|
154
153
|
- lib/experiment/local/client.rb
|
155
154
|
- lib/experiment/local/config.rb
|
156
155
|
- lib/experiment/local/evaluation/evaluation.rb
|
@@ -163,7 +162,6 @@ files:
|
|
163
162
|
- lib/experiment/local/evaluation/lib/macosX64/libevaluation_interop.dylib
|
164
163
|
- lib/experiment/local/evaluation/lib/macosX64/libevaluation_interop_api.h
|
165
164
|
- lib/experiment/local/fetcher.rb
|
166
|
-
- lib/experiment/local/poller.rb
|
167
165
|
- lib/experiment/persistent_http_client.rb
|
168
166
|
- lib/experiment/remote/client.rb
|
169
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
|