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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 264b075c9fe812647617e67dc99c5a6baf91e4951e32617a8da612570f43001b
4
- data.tar.gz: c197188d0084bb00618e578e57bcd0fc0235517218b718ce04d128b3a61c2d58
3
+ metadata.gz: ff36301b51f9c519b85c5361aa6e50e45d0e55738ee6d36e10b3599e6b91b98b
4
+ data.tar.gz: 6e03119d4dd2b6f33c4f0ba312043aac2eb688f211cf827a046d90457a40dcdb
5
5
  SHA512:
6
- metadata.gz: 3a5e609cd8a605fe6612c9979840e5dd57ed4994aece4f559c51ac2ed7cb881916edbc1428eec0f1b2f373e2423c262293a6dee0005ed848722125a7167d7ec0
7
- data.tar.gz: ef2db5134be745c70e61fd5f9647512f1202966d509f3785409ae540d6846d0013b55f694b84881b933b56b4c2489ab028939f63c629db26dff77ef45340cb33
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
@@ -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
- @cache = InMemoryFlagConfigCache.new(@config.bootstrap)
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
- flag_configs = []
36
- if flag_keys.empty?
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
- flag_configs_str = flag_configs.to_json
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
- variant_key = value['variant']['key']
54
- variant_payload = value['variant']['payload']
55
- variants.store(key, Variant.new(variant_key, variant_payload))
56
- end
57
- variants
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
- @poller.start
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
- @poller.stop
57
+ @poller_thread&.exit
58
+ @is_running = false
59
+ @poller_thread = nil
69
60
  end
70
61
 
71
62
  private
72
63
 
73
- def get_flag_configs(flag_keys = [])
74
- return @cache.cache if flag_keys.empty?
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
- flag_configs = []
77
- flag_keys.each do |key|
78
- flag_config = @cache.get(key)
79
- flag_configs.push(flag_config) if flag_config
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 server endpoint from which to request variants.
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
 
@@ -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 {
@@ -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 {
@@ -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 {
@@ -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
- @uri = "#{server_url}/sdk/rules?eval_mode=local"
10
+ @server_url = server_url
11
11
  @debug = debug
12
- @http = PersistentHttpClient.get(@uri, { read_timeout: FLAG_CONFIG_TIMEOUT })
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(@uri, headers)
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
 
@@ -1,3 +1,3 @@
1
1
  module AmplitudeExperiment
2
- VERSION = '1.0.1'.freeze
2
+ VERSION = '1.1.0'.freeze
3
3
  end
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.1
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: 2022-12-12 00:00:00.000000000 Z
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