devcycle-ruby-server-sdk 2.7.0 → 3.0.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: 339be985589c9cf266b4407fd9a5204427a15d65ecb038e82ad4d9ecb691d92b
4
- data.tar.gz: 17f111831f10133475bc0823e63c043f2e264eaa2fd824a6041892da1986f2d8
3
+ metadata.gz: 2f9dd2899f5a8f286a66a667fa27623331572f5c35dec9ad363ab0be2e191296
4
+ data.tar.gz: e0971e7a1bdafc366b2021df303dbfc0f30f230d1c353e435d810805026ab866
5
5
  SHA512:
6
- metadata.gz: b02d9c440efd5eaf673a50dd94b71ed14edf4fcd8d08c0ee21d68626470664a9c0c3daf1fb6c0f01478da66b7195bba0b474a4264a91df50a7ead0ad7f1dc5fd
7
- data.tar.gz: 13079629f20070367b1bbb87b84b3d1579bce357e2255857cae86707c4fb205d6f9a13f7d56daeaaf278c6a82b82411bc72e5855d455575b4c21dfcda1b5b6d2
6
+ metadata.gz: 0c2d2b26b6ef08f548c58ecfbca13b2a09ab5643184f2018f9ede3e41ca1a115f17024f577e84ce12c27a23161be3cb7dc0d717569d23f4698b1f0398847dfdf
7
+ data.tar.gz: 1bfe5568cc56cf86566c9fe9d7480ffb6b3f7edf6907544a3305e99fbe64a163a867aa8f713015172591673889bd688fd81971efd4fbb91ef152433c59637b61
data/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
- gem 'sorbet-runtime'
4
+ gem 'sorbet-runtime', '0.5.11481'
5
5
  gem 'oj'
6
6
  gem 'wasmtime'
7
7
  gem 'concurrent-ruby'
@@ -21,12 +21,12 @@ Gem::Specification.new do |s|
21
21
  s.summary = "DevCycle Bucketing API Ruby Gem"
22
22
  s.description = "DevCycle Ruby Server SDK, for interacting with feature flags created with the DevCycle platform."
23
23
  s.license = "MIT"
24
- s.required_ruby_version = ">= 2.4"
24
+ s.required_ruby_version = ">= 3.1"
25
25
 
26
26
  s.add_runtime_dependency 'typhoeus', '~> 1.0', '>= 1.0.1'
27
- s.add_runtime_dependency 'wasmtime', '13.0.0'
27
+ s.add_runtime_dependency 'wasmtime', '20.0.2'
28
28
  s.add_runtime_dependency 'concurrent-ruby', '~> 1.2.0'
29
- s.add_runtime_dependency 'sorbet-runtime', '~> 0.5'
29
+ s.add_runtime_dependency 'sorbet-runtime', '>= 0.5.11481'
30
30
  s.add_runtime_dependency 'oj', '~> 3.0'
31
31
  s.add_runtime_dependency 'google-protobuf', '~> 3.22'
32
32
 
@@ -158,13 +158,13 @@ module DevCycle
158
158
  end
159
159
 
160
160
  # Get variable by key for user data
161
- # @param user [User]
161
+ # @param user [DevCycle::User]
162
162
  # @param key [String] Variable key
163
163
  # @param default Default value for variable if none is retrieved
164
164
  # @param [Hash] opts the optional parameters
165
165
  # @return [Variable]
166
166
  def variable(user, key, default, opts = {})
167
- if !user.is_a?(DevCycle::User)
167
+ unless user.is_a?(DevCycle::User)
168
168
  fail ArgumentError, "user param must be an instance of DevCycle::User!"
169
169
  end
170
170
 
@@ -4,6 +4,7 @@ require 'sorbet-runtime'
4
4
  require 'concurrent-ruby'
5
5
  require 'typhoeus'
6
6
  require 'json'
7
+ require 'time'
7
8
 
8
9
  module DevCycle
9
10
  class ConfigManager
@@ -19,13 +20,14 @@ module DevCycle
19
20
  @local_bucketing = local_bucketing
20
21
  @sdkKey = sdkKey
21
22
  @config_e_tag = ""
23
+ @config_last_modified = ""
22
24
  @logger = local_bucketing.options.logger
23
25
  @polling_enabled = true
24
26
  @max_config_retries = 2
25
27
 
26
28
  @config_poller = Concurrent::TimerTask.new({
27
- execution_interval: @local_bucketing.options.config_polling_interval_ms.fdiv(1000)
28
- }) do |task|
29
+ execution_interval: @local_bucketing.options.config_polling_interval_ms.fdiv(1000)
30
+ }) do |task|
29
31
  fetch_config
30
32
  end
31
33
 
@@ -53,22 +55,43 @@ module DevCycle
53
55
  Accept: "application/json",
54
56
  })
55
57
 
58
+ begin
59
+ Date.parse(@config_last_modified)
60
+ if @config_last_modified != ""
61
+ req.options[:headers]["If-Modified-Since"] = Time.httpdate(@config_last_modified)
62
+ end
63
+ rescue
64
+ end
65
+
66
+
56
67
  if @config_e_tag != ""
57
68
  req.options[:headers]['If-None-Match'] = @config_e_tag
58
69
  end
59
70
 
60
71
  @max_config_retries.times do
61
- @logger.debug("Requesting new config from #{get_config_url}, current etag: #{@config_e_tag}")
72
+ @logger.debug("Requesting new config from #{get_config_url}, current etag: #{@config_e_tag}, last modified: #{@config_last_modified}")
62
73
  resp = req.run
63
74
  @logger.debug("Config request complete, status: #{resp.code}")
64
75
  case resp.code
65
76
  when 304
66
- @logger.debug("Config not modified, using cache, etag: #{@config_e_tag}")
77
+ @logger.debug("Config not modified, using cache, etag: #{@config_e_tag}, last modified: #{@config_last_modified}")
67
78
  break
68
79
  when 200
69
- @logger.debug("New config received, etag: #{resp.headers['Etag']}")
70
- set_config(resp.body, resp.headers['Etag'])
71
- @logger.debug("New config stored, etag: #{@config_e_tag}")
80
+ @logger.debug("New config received, etag: #{resp.headers['Etag']} LM:#{resp.headers['Last-Modified']}")
81
+ lm_header = resp.headers['Last-Modified']
82
+ begin
83
+ lm_timestamp = Time.rfc2822(lm_header)
84
+ current_lm = Time.rfc2822(@config_last_modified)
85
+ if lm_timestamp == "" && @config_last_modified == "" || (current_lm.utc < lm_timestamp.utc)
86
+ set_config(resp.body, resp.headers['Etag'], lm_header)
87
+ @logger.debug("New config stored, etag: #{@config_e_tag}, last modified: #{lm_header}")
88
+ else
89
+ @logger.warn("Config response was an older config than currently stored config.")
90
+ end
91
+ rescue
92
+ @logger.warn("Failed to parse last modified header, setting config.")
93
+ set_config(resp.body, resp.headers['Etag'], lm_header)
94
+ end
72
95
  break
73
96
  when 403
74
97
  stop_polling
@@ -91,13 +114,14 @@ module DevCycle
91
114
  nil
92
115
  end
93
116
 
94
- def set_config(config, etag)
117
+ def set_config(config, etag, lastmodified)
95
118
  if !JSON.parse(config).is_a?(Hash)
96
119
  raise("Invalid JSON body parsed from Config Response")
97
120
  end
98
121
 
99
122
  @local_bucketing.store_config(config)
100
123
  @config_e_tag = etag
124
+ @config_last_modified = lastmodified
101
125
  @local_bucketing.has_config = true
102
126
  end
103
127
 
@@ -1,6 +1,8 @@
1
1
  require 'typhoeus'
2
2
  require 'sorbet-runtime'
3
3
  require 'concurrent-ruby'
4
+ require 'securerandom'
5
+
4
6
 
5
7
  module DevCycle
6
8
  class EventQueue
@@ -9,6 +11,7 @@ module DevCycle
9
11
  sig { params(sdkKey: String, options: EventQueueOptions, local_bucketing: LocalBucketing).void }
10
12
  def initialize(sdkKey, options, local_bucketing)
11
13
  @sdkKey = sdkKey
14
+ @client_uuid = SecureRandom.uuid
12
15
  @events_api_uri = options.events_api_uri
13
16
  @logger = options.logger
14
17
  @event_flush_interval_ms = options.event_flush_interval_ms
@@ -22,7 +25,7 @@ module DevCycle
22
25
  @flush_timer_task.execute
23
26
  @flush_mutex = Mutex.new
24
27
  @local_bucketing = local_bucketing
25
- @local_bucketing.init_event_queue(options)
28
+ @local_bucketing.init_event_queue(@client_uuid, options)
26
29
  end
27
30
 
28
31
  def close
@@ -32,6 +32,7 @@ module DevCycle
32
32
  .inherit_stderr
33
33
  .set_argv(ARGV)
34
34
  .set_env(ENV)
35
+ .build
35
36
  @@store = Wasmtime::Store.new(@@engine, wasi_ctx: @@wasi_ctx)
36
37
  @@linker = Wasmtime::Linker.new(@@engine, wasi: true)
37
38
 
@@ -245,13 +246,14 @@ module DevCycle
245
246
  end
246
247
  end
247
248
 
248
- sig { params(options: EventQueueOptions).returns(NilClass) }
249
- def init_event_queue(options)
249
+ sig { params(client_uuid: String, options: EventQueueOptions).returns(NilClass) }
250
+ def init_event_queue(client_uuid, options)
250
251
  @wasm_mutex.synchronize do
251
252
  options_json = Oj.dump(options)
253
+ client_uuid_addr = malloc_asc_string(client_uuid)
252
254
  options_addr = malloc_asc_string(options_json)
253
255
  @@stack_tracer = @@stack_tracer_raise
254
- @@instance.invoke("initEventQueue", @sdkKeyAddr, options_addr)
256
+ @@instance.invoke("initEventQueue", @sdkKeyAddr, client_uuid_addr, options_addr)
255
257
  end
256
258
  end
257
259
 
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+ BUCKETING_LIB_VERSION="1.24.2"
3
+ WAT_DOWNLOAD=0
4
+ rm bucketing-lib.release.wasm
5
+ wget "https://unpkg.com/@devcycle/bucketing-assembly-script@$BUCKETING_LIB_VERSION/build/bucketing-lib.release.wasm"
@@ -11,5 +11,5 @@ OpenAPI Generator version: 5.3.0
11
11
  =end
12
12
 
13
13
  module DevCycle
14
- VERSION = '2.7.0'
14
+ VERSION = '3.0.0'
15
15
  end
@@ -93,7 +93,7 @@ describe 'DevCycle::Client' do
93
93
  it 'should work' do
94
94
  result = @api_instance.all_variables(@user)
95
95
 
96
- expect(result.length).to eq 1
96
+ expect(result.length).to eq 5
97
97
  end
98
98
  end
99
99
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devcycle-ruby-server-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - DevCycleHQ
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-15 00:00:00.000000000 Z
11
+ date: 2024-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: typhoeus
@@ -36,14 +36,14 @@ dependencies:
36
36
  requirements:
37
37
  - - '='
38
38
  - !ruby/object:Gem::Version
39
- version: 13.0.0
39
+ version: 20.0.2
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - '='
45
45
  - !ruby/object:Gem::Version
46
- version: 13.0.0
46
+ version: 20.0.2
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: concurrent-ruby
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -62,16 +62,16 @@ dependencies:
62
62
  name: sorbet-runtime
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - "~>"
65
+ - - ">="
66
66
  - !ruby/object:Gem::Version
67
- version: '0.5'
67
+ version: 0.5.11481
68
68
  type: :runtime
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - "~>"
72
+ - - ">="
73
73
  - !ruby/object:Gem::Version
74
- version: '0.5'
74
+ version: 0.5.11481
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: oj
77
77
  requirement: !ruby/object:Gem::Requirement
@@ -149,6 +149,7 @@ files:
149
149
  - lib/devcycle-ruby-server-sdk/localbucketing/proto/helpers.rb
150
150
  - lib/devcycle-ruby-server-sdk/localbucketing/proto/variableForUserParams.proto
151
151
  - lib/devcycle-ruby-server-sdk/localbucketing/proto/variableForUserParams_pb.rb
152
+ - lib/devcycle-ruby-server-sdk/localbucketing/update_wasm.sh
152
153
  - lib/devcycle-ruby-server-sdk/models/error_response.rb
153
154
  - lib/devcycle-ruby-server-sdk/models/event.rb
154
155
  - lib/devcycle-ruby-server-sdk/models/feature.rb
@@ -173,14 +174,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
173
174
  requirements:
174
175
  - - ">="
175
176
  - !ruby/object:Gem::Version
176
- version: '2.4'
177
+ version: '3.1'
177
178
  required_rubygems_version: !ruby/object:Gem::Requirement
178
179
  requirements:
179
180
  - - ">="
180
181
  - !ruby/object:Gem::Version
181
182
  version: '0'
182
183
  requirements: []
183
- rubygems_version: 3.2.33
184
+ rubygems_version: 3.4.1
184
185
  signing_key:
185
186
  specification_version: 4
186
187
  summary: DevCycle Bucketing API Ruby Gem