statsig 1.29.0.pre.beta.1 → 1.29.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e279228e9eb701b7bcf06ac68ada05a4403f1d046c4ddc3343c87cf86d6be049
4
- data.tar.gz: 3b110f44f460c9924aa909c1e9723094189a0fe4a20c6f7572c997cf40968e29
3
+ metadata.gz: '093cc05e0b8f3bb7e2f0f019cf36ad33e5abc4c4349d2fb1faa056c1ff5aa341'
4
+ data.tar.gz: d66640f8b0c317ca018ff4ccc77d1d370af89b1c84416508631deb610236d519
5
5
  SHA512:
6
- metadata.gz: a4871a883213685bc1d6c537367f4de78cacc81b0cec6929853b57c80439895e0ed49d797ef5bb7733c5dce73df9c0bb1aa5ef4b8c3563351468b557f3e473b4
7
- data.tar.gz: fbdc2952ed68a92640268c6931b59521e641d22448c2c8a897521637951d7c20ea6f0f6d4354252c184a8a1c0b9e03861f9b047c9634165998f6a9218660e7e6
6
+ metadata.gz: f634575320cd1ababfa25816ee8ac5fe27e34c761895b4ba6b20957363e487c295767d65e123ab7d306aa1ce2f535f55cc58570f8767790948d2647ab321150b
7
+ data.tar.gz: d563727b175a23afa50cb68cbaf91eb49435bae46b1a48b72d9bf0ff38febeefa86b886c34cc2632f37e357c44f96a1e2586050b41e9ac156697f4105c4f9f0b
@@ -42,7 +42,7 @@ module ClientInitializeHelpers
42
42
  target_app_id = @evaluator.spec_store.get_app_id_for_sdk_key(@client_sdk_key)
43
43
  config_target_apps = config_spec['targetAppIDs']
44
44
 
45
- unless target_app_id.nil? || config_target_apps.nil? || config_target_apps.include?(target_app_id)
45
+ unless target_app_id.nil? || (!config_target_apps.nil? && config_target_apps.include?(target_app_id))
46
46
  return nil
47
47
  end
48
48
 
data/lib/config_result.rb CHANGED
@@ -25,7 +25,7 @@ module Statsig
25
25
  json_value = {},
26
26
  rule_id = '',
27
27
  secondary_exposures = [],
28
- config_delegate = '',
28
+ config_delegate = nil,
29
29
  explicit_parameters = [],
30
30
  is_experiment_group: false,
31
31
  evaluation_details: nil,
data/lib/layer.rb CHANGED
@@ -17,11 +17,25 @@ class Layer
17
17
  sig { returns(String) }
18
18
  attr_accessor :rule_id
19
19
 
20
- sig { params(name: String, value: T::Hash[String, T.untyped], rule_id: String, exposure_log_func: T.any(Method, Proc, NilClass)).void }
21
- def initialize(name, value = {}, rule_id = '', exposure_log_func = nil)
20
+ sig { returns(String) }
21
+ attr_accessor :group_name
22
+
23
+ sig do
24
+ params(
25
+ name: String,
26
+ value: T::Hash[String, T.untyped],
27
+ rule_id: String,
28
+ group_name: T.nilable(String),
29
+ allocated_experiment: T.nilable(String),
30
+ exposure_log_func: T.any(Method, Proc, NilClass)
31
+ ).void
32
+ end
33
+ def initialize(name, value = {}, rule_id = '', group_name = nil, allocated_experiment = nil, exposure_log_func = nil)
22
34
  @name = name
23
35
  @value = value
24
36
  @rule_id = rule_id
37
+ @group_name = group_name
38
+ @allocated_experiment = allocated_experiment
25
39
  @exposure_log_func = exposure_log_func
26
40
  end
27
41
 
@@ -58,4 +72,4 @@ class Layer
58
72
 
59
73
  @value[index]
60
74
  end
61
- end
75
+ end
data/lib/network.rb CHANGED
@@ -53,11 +53,42 @@ module Statsig
53
53
  end
54
54
  end
55
55
 
56
+ sig do
57
+ params(since_time: Integer)
58
+ .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)])
59
+ end
60
+ def download_config_specs(since_time)
61
+ get("download_config_specs/#{@server_secret}.json?sinceTime=#{since_time}")
62
+ end
63
+
64
+ class HttpMethod < T::Enum
65
+ enums do
66
+ GET = new
67
+ POST = new
68
+ end
69
+ end
70
+
71
+ sig do
72
+ params(endpoint: String, retries: Integer, backoff: Integer)
73
+ .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)])
74
+ end
75
+ def get(endpoint, retries = 0, backoff = 1)
76
+ request(HttpMethod::GET, endpoint, nil, retries, backoff)
77
+ end
78
+
56
79
  sig do
57
80
  params(endpoint: String, body: String, retries: Integer, backoff: Integer)
58
81
  .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)])
59
82
  end
60
- def post_helper(endpoint, body, retries = 0, backoff = 1)
83
+ def post(endpoint, body, retries = 0, backoff = 1)
84
+ request(HttpMethod::POST, endpoint, body, retries, backoff)
85
+ end
86
+
87
+ sig do
88
+ params(method: HttpMethod, endpoint: String, body: T.nilable(String), retries: Integer, backoff: Integer)
89
+ .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)])
90
+ end
91
+ def request(method, endpoint, body, retries = 0, backoff = 1)
61
92
  if @local_mode
62
93
  return nil, nil
63
94
  end
@@ -73,14 +104,20 @@ module Statsig
73
104
  url = URIHelper.build_url(endpoint)
74
105
  begin
75
106
  res = @connection_pool.with do |conn|
76
- conn.headers('STATSIG-CLIENT-TIME' => (Time.now.to_f * 1000).to_i.to_s).post(url, body: body)
107
+ request = conn.headers('STATSIG-CLIENT-TIME' => (Time.now.to_f * 1000).to_i.to_s)
108
+ case method
109
+ when HttpMethod::GET
110
+ request.get(url)
111
+ when HttpMethod::POST
112
+ request.post(url, body: body)
113
+ end
77
114
  end
78
115
  rescue StandardError => e
79
116
  ## network error retry
80
117
  return nil, e unless retries.positive?
81
118
 
82
119
  sleep backoff_adjusted
83
- return post_helper(endpoint, body, retries - 1, backoff * @backoff_multiplier)
120
+ return request(method, endpoint, body, retries - 1, backoff * @backoff_multiplier)
84
121
  end
85
122
  return res, nil if res.status.success?
86
123
 
@@ -91,12 +128,12 @@ module Statsig
91
128
 
92
129
  ## status code retry
93
130
  sleep backoff_adjusted
94
- post_helper(endpoint, body, retries - 1, backoff * @backoff_multiplier)
131
+ request(method, endpoint, body, retries - 1, backoff * @backoff_multiplier)
95
132
  end
96
133
 
97
134
  def check_gate(user, gate_name)
98
135
  request_body = JSON.generate({ 'user' => user&.serialize(false), 'gateName' => gate_name })
99
- response, = post_helper('check_gate', request_body)
136
+ response, = post('check_gate', request_body)
100
137
  return JSON.parse(response.body) unless response.nil?
101
138
 
102
139
  false
@@ -106,7 +143,7 @@ module Statsig
106
143
 
107
144
  def get_config(user, dynamic_config_name)
108
145
  request_body = JSON.generate({ 'user' => user&.serialize(false), 'configName' => dynamic_config_name })
109
- response, = post_helper('get_config', request_body)
146
+ response, = post('get_config', request_body)
110
147
  return JSON.parse(response.body) unless response.nil?
111
148
 
112
149
  nil
@@ -116,7 +153,7 @@ module Statsig
116
153
 
117
154
  def post_logs(events)
118
155
  json_body = JSON.generate({ 'events' => events, 'statsigMetadata' => Statsig.get_statsig_metadata })
119
- post_helper('log_event', json_body, @post_logs_retry_limit)
156
+ post('log_event', json_body, @post_logs_retry_limit)
120
157
  rescue StandardError
121
158
 
122
159
  end
data/lib/spec_store.rb CHANGED
@@ -238,7 +238,7 @@ module Statsig
238
238
 
239
239
  error = nil
240
240
  begin
241
- response, e = @network.post_helper('download_config_specs', JSON.generate({ 'sinceTime' => @last_config_sync_time }))
241
+ response, e = @network.download_config_specs(@last_config_sync_time)
242
242
  code = response&.status.to_i
243
243
  if e.is_a? NetworkError
244
244
  code = e.http_code
@@ -334,7 +334,7 @@ module Statsig
334
334
 
335
335
  def get_id_lists_from_network
336
336
  tracker = @diagnostics.track('get_id_list_sources', 'network_request')
337
- response, e = @network.post_helper('get_id_lists', JSON.generate({ 'statsigMetadata' => Statsig.get_statsig_metadata }))
337
+ response, e = @network.post('get_id_lists', JSON.generate({ 'statsigMetadata' => Statsig.get_statsig_metadata }))
338
338
  code = response&.status.to_i
339
339
  if e.is_a? NetworkError
340
340
  code = e.http_code
data/lib/statsig.rb CHANGED
@@ -265,7 +265,7 @@ module Statsig
265
265
  def self.get_statsig_metadata
266
266
  {
267
267
  'sdkType' => 'ruby-server',
268
- 'sdkVersion' => '1.29.0-beta.1',
268
+ 'sdkVersion' => '1.29.0',
269
269
  }
270
270
  end
271
271
 
@@ -130,7 +130,7 @@ class StatsigDriver
130
130
  end
131
131
 
132
132
  if res == $fetch_from_server
133
- if res.config_delegate.empty?
133
+ if res.config_delegate.nil?
134
134
  return Layer.new(layer_name)
135
135
  end
136
136
  res = get_config_fallback(user, res.config_delegate)
@@ -140,7 +140,7 @@ class StatsigDriver
140
140
  exposure_log_func = !options.disable_log_exposure ? lambda { |layer, parameter_name|
141
141
  @logger.log_layer_exposure(user, layer, parameter_name, res)
142
142
  } : nil
143
- Layer.new(res.name, res.json_value, res.rule_id, exposure_log_func)
143
+ Layer.new(res.name, res.json_value, res.rule_id, res.group_name, res.config_delegate, exposure_log_func)
144
144
  }, caller: __method__.to_s)
145
145
  }, recover: lambda { Layer.new(layer_name) }, caller: __method__.to_s)
146
146
  end
@@ -149,7 +149,7 @@ class StatsigDriver
149
149
  def manually_log_layer_parameter_exposure(user, layer_name, parameter_name)
150
150
  @err_boundary.capture(task: lambda {
151
151
  res = @evaluator.get_layer(user, layer_name)
152
- layer = Layer.new(layer_name, res.json_value, res.rule_id)
152
+ layer = Layer.new(layer_name, res.json_value, res.rule_id, res.group_name, res.config_delegate)
153
153
  context = { 'is_manual_exposure' => true }
154
154
  @logger.log_layer_exposure(user, layer, parameter_name, res, context)
155
155
  }, caller: __method__.to_s)
@@ -22,7 +22,7 @@ class StatsigOptions
22
22
 
23
23
  # The base url used specifically to call download_config_specs.
24
24
  # Takes precedence over api_url_base
25
- sig { returns(T.any(String, NilClass)) }
25
+ sig { returns(String) }
26
26
  attr_accessor :api_url_download_config_specs
27
27
 
28
28
  sig { returns(T.any(Float, Integer)) }
@@ -115,7 +115,7 @@ class StatsigOptions
115
115
  sig do
116
116
  params(
117
117
  environment: T.any(T::Hash[String, String], NilClass),
118
- api_url_base: String,
118
+ api_url_base: T.nilable(String),
119
119
  api_url_download_config_specs: T.any(String, NilClass),
120
120
  rulesets_sync_interval: T.any(Float, Integer),
121
121
  idlists_sync_interval: T.any(Float, Integer),
@@ -137,10 +137,9 @@ class StatsigOptions
137
137
  user_persistent_storage: T.any(Statsig::Interfaces::IUserPersistentStorage, NilClass)
138
138
  ).void
139
139
  end
140
-
141
140
  def initialize(
142
141
  environment = nil,
143
- api_url_base = 'https://statsigapi.net/v1',
142
+ api_url_base = nil,
144
143
  api_url_download_config_specs: nil,
145
144
  rulesets_sync_interval: 10,
146
145
  idlists_sync_interval: 60,
@@ -162,8 +161,8 @@ class StatsigOptions
162
161
  user_persistent_storage: nil
163
162
  )
164
163
  @environment = environment.is_a?(Hash) ? environment : nil
165
- @api_url_base = api_url_base
166
- @api_url_download_config_specs = api_url_download_config_specs
164
+ @api_url_base = api_url_base || 'https://statsigapi.net/v1'
165
+ @api_url_download_config_specs = api_url_download_config_specs || api_url_base || 'https://api.statsigcdn.com/v1'
167
166
  @rulesets_sync_interval = rulesets_sync_interval
168
167
  @idlists_sync_interval = idlists_sync_interval
169
168
  @disable_rulesets_sync = disable_rulesets_sync
data/lib/uri_helper.rb CHANGED
@@ -17,7 +17,7 @@ class URIHelper
17
17
  sig { params(endpoint: String).returns(String) }
18
18
  def build_url(endpoint)
19
19
  api = @options.api_url_base
20
- if endpoint == 'download_config_specs' && !@options.api_url_download_config_specs.nil?
20
+ if endpoint.include?('download_config_specs')
21
21
  api = T.must(@options.api_url_download_config_specs)
22
22
  end
23
23
  unless api.end_with?('/')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: statsig
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.29.0.pre.beta.1
4
+ version: 1.29.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Statsig, Inc
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-11 00:00:00.000000000 Z
11
+ date: 2023-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -351,7 +351,7 @@ homepage: https://rubygems.org/gems/statsig
351
351
  licenses:
352
352
  - ISC
353
353
  metadata: {}
354
- post_install_message:
354
+ post_install_message:
355
355
  rdoc_options: []
356
356
  require_paths:
357
357
  - lib
@@ -362,12 +362,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
362
362
  version: 2.5.0
363
363
  required_rubygems_version: !ruby/object:Gem::Requirement
364
364
  requirements:
365
- - - ">"
365
+ - - ">="
366
366
  - !ruby/object:Gem::Version
367
- version: 1.3.1
367
+ version: '0'
368
368
  requirements: []
369
- rubygems_version: 3.3.7
370
- signing_key:
369
+ rubygems_version: 3.2.33
370
+ signing_key:
371
371
  specification_version: 4
372
372
  summary: Statsig server SDK for Ruby
373
373
  test_files: []