devcycle-ruby-server-sdk 2.0.1 → 2.0.2
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/devcycle-ruby-server-sdk.gemspec +2 -2
- data/lib/devcycle-ruby-server-sdk/api/devcycle_api.rb +3 -2
- data/lib/devcycle-ruby-server-sdk/localbucketing/config_manager.rb +2 -3
- data/lib/devcycle-ruby-server-sdk/localbucketing/dvc_options.rb +20 -14
- data/lib/devcycle-ruby-server-sdk/localbucketing/event_queue.rb +3 -22
- data/lib/devcycle-ruby-server-sdk/localbucketing/local_bucketing.rb +48 -32
- data/lib/devcycle-ruby-server-sdk/version.rb +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 86e5a04ee7157791c8ed075df281ecc09bad3ae898c7e48d520046953ed5aee7
|
4
|
+
data.tar.gz: 44271e4418ab7b2219403d9a90bbc702befabb034446bc58a2f32a365038f9cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5946e97ac8b2d0abda40af307609035945e1881587edc5d1d37c01fc1f75e9e0461527f3c232713ba0c839834b2447e4ab95a3f7a471e314fe28c01c15f3281
|
7
|
+
data.tar.gz: 147519317a620feef9d975bcb3a5cb844c94e03b7f6fb8631d34e98b57b770a5994c4324dd9c1359e7e744b0b5652f6a5f612fdbc0f68a600816187717b22c43
|
@@ -25,8 +25,8 @@ Gem::Specification.new do |s|
|
|
25
25
|
|
26
26
|
s.add_runtime_dependency 'typhoeus', '~> 1.0', '>= 1.0.1'
|
27
27
|
s.add_runtime_dependency 'wasmtime', '5.0.0'
|
28
|
-
s.add_runtime_dependency 'concurrent-ruby', '1.2.0'
|
29
|
-
s.add_runtime_dependency 'sorbet-runtime', '0.5
|
28
|
+
s.add_runtime_dependency 'concurrent-ruby', '~> 1.2.0'
|
29
|
+
s.add_runtime_dependency 'sorbet-runtime', '~> 0.5'
|
30
30
|
s.add_runtime_dependency 'oj', '3.13.2'
|
31
31
|
|
32
32
|
|
@@ -17,9 +17,9 @@ module DevCycle
|
|
17
17
|
class DVCClient
|
18
18
|
def initialize(sdkKey, dvc_options = DVCOptions.new, wait_for_init = false)
|
19
19
|
if sdkKey.nil?
|
20
|
-
raise ArgumentError('Missing SDK key!')
|
20
|
+
raise ArgumentError.new('Missing SDK key!')
|
21
21
|
elsif !sdkKey.start_with?('server') && !sdkKey.start_with?('dvc_server')
|
22
|
-
raise ArgumentError('Invalid SDK key!')
|
22
|
+
raise ArgumentError.new('Invalid SDK key!')
|
23
23
|
end
|
24
24
|
|
25
25
|
@sdkKey = sdkKey
|
@@ -56,6 +56,7 @@ module DevCycle
|
|
56
56
|
|
57
57
|
@event_queue.close
|
58
58
|
@logger.info("Closed DevCycle Client.")
|
59
|
+
nil
|
59
60
|
end
|
60
61
|
|
61
62
|
def set_client_custom_data(customdata)
|
@@ -23,8 +23,7 @@ module DevCycle
|
|
23
23
|
|
24
24
|
@config_poller = Concurrent::TimerTask.new(
|
25
25
|
{
|
26
|
-
execution_interval: @local_bucketing.options.config_polling_interval_ms.fdiv(1000)
|
27
|
-
run_now: true
|
26
|
+
execution_interval: @local_bucketing.options.config_polling_interval_ms.fdiv(1000)
|
28
27
|
}) do |task|
|
29
28
|
fetch_config(false, task)
|
30
29
|
end
|
@@ -73,7 +72,7 @@ module DevCycle
|
|
73
72
|
raise("Invalid JSON body parsed from Config Response")
|
74
73
|
end
|
75
74
|
|
76
|
-
@local_bucketing.store_config(
|
75
|
+
@local_bucketing.store_config(config)
|
77
76
|
@config_e_tag = etag
|
78
77
|
|
79
78
|
if @first_load
|
@@ -12,15 +12,16 @@ module DevCycle
|
|
12
12
|
|
13
13
|
def initialize(
|
14
14
|
enable_cloud_bucketing: false,
|
15
|
-
event_flush_interval_ms:
|
15
|
+
event_flush_interval_ms: 10_000,
|
16
16
|
disable_custom_event_logging: false,
|
17
17
|
disable_automatic_event_logging: false,
|
18
|
-
config_polling_interval_ms:
|
19
|
-
request_timeout_ms:
|
20
|
-
max_event_queue_size:
|
21
|
-
flush_event_queue_size:
|
18
|
+
config_polling_interval_ms: 10_000,
|
19
|
+
request_timeout_ms: 5_000,
|
20
|
+
max_event_queue_size: 2_000,
|
21
|
+
flush_event_queue_size: 1_000,
|
22
22
|
event_request_chunk_size: 100,
|
23
23
|
logger: nil,
|
24
|
+
config_cdn_uri: 'https://config-cdn.devcycle.com',
|
24
25
|
events_api_uri: 'https://events.devcycle.com',
|
25
26
|
enable_edge_db: false
|
26
27
|
)
|
@@ -34,8 +35,7 @@ module DevCycle
|
|
34
35
|
end
|
35
36
|
|
36
37
|
if config_polling_interval_ms < 1000
|
37
|
-
|
38
|
-
config_polling_interval_ms = 10000
|
38
|
+
raise ArgumentError.new('config_polling_interval cannot be less than 1000ms')
|
39
39
|
end
|
40
40
|
@config_polling_interval_ms = config_polling_interval_ms
|
41
41
|
|
@@ -51,15 +51,21 @@ module DevCycle
|
|
51
51
|
@event_flush_interval_ms = event_flush_interval_ms
|
52
52
|
|
53
53
|
if flush_event_queue_size >= max_event_queue_size
|
54
|
-
raise ArgumentError.new(
|
55
|
-
"
|
54
|
+
raise ArgumentError.new(
|
55
|
+
"flush_event_queue_size: #{flush_event_queue_size} must be " +
|
56
|
+
"smaller than max_event_queue_size: #{@max_event_queue_size}"
|
57
|
+
)
|
56
58
|
elsif flush_event_queue_size < event_request_chunk_size || max_event_queue_size < event_request_chunk_size
|
57
|
-
throw ArgumentError.new(
|
59
|
+
throw ArgumentError.new(
|
60
|
+
"flush_event_queue_size: #{flush_event_queue_size} and " +
|
58
61
|
"max_event_queue_size: #{max_event_queue_size} " +
|
59
|
-
"must be larger than event_request_chunk_size: #{event_request_chunk_size}"
|
62
|
+
"must be larger than event_request_chunk_size: #{event_request_chunk_size}"
|
63
|
+
)
|
60
64
|
elsif flush_event_queue_size > 20000 || max_event_queue_size > 20000
|
61
|
-
raise ArgumentError.new(
|
62
|
-
"
|
65
|
+
raise ArgumentError.new(
|
66
|
+
"flush_event_queue_size: #{flush_event_queue_size} or " +
|
67
|
+
"max_event_queue_size: #{max_event_queue_size} must be smaller than 20,000"
|
68
|
+
)
|
63
69
|
end
|
64
70
|
@flush_event_queue_size = flush_event_queue_size
|
65
71
|
@max_event_queue_size = max_event_queue_size
|
@@ -67,7 +73,7 @@ module DevCycle
|
|
67
73
|
|
68
74
|
@disable_custom_event_logging = disable_custom_event_logging
|
69
75
|
@disable_automatic_event_logging = disable_automatic_event_logging
|
70
|
-
@config_cdn_uri =
|
76
|
+
@config_cdn_uri = config_cdn_uri
|
71
77
|
@events_api_uri = events_api_uri
|
72
78
|
@bucketing_api_uri = "https://bucketing-api.devcyle.com"
|
73
79
|
end
|
@@ -14,21 +14,15 @@ module DevCycle
|
|
14
14
|
@event_flush_interval_ms = options.event_flush_interval_ms
|
15
15
|
@flush_event_queue_size = options.flush_event_queue_size
|
16
16
|
@max_event_queue_size = options.max_event_queue_size
|
17
|
-
|
18
17
|
@flush_timer_task = Concurrent::TimerTask.new(
|
19
|
-
execution_interval: @event_flush_interval_ms.fdiv(1000)
|
20
|
-
run_now: true
|
18
|
+
execution_interval: @event_flush_interval_ms.fdiv(1000)
|
21
19
|
) {
|
22
20
|
flush_events
|
23
21
|
}
|
24
22
|
@flush_timer_task.execute
|
25
|
-
@
|
26
|
-
|
23
|
+
@flush_mutex = Mutex.new
|
27
24
|
@local_bucketing = local_bucketing
|
28
25
|
@local_bucketing.init_event_queue(options)
|
29
|
-
|
30
|
-
@flush_mutex = Mutex.new
|
31
|
-
nil
|
32
26
|
end
|
33
27
|
|
34
28
|
def close
|
@@ -50,7 +44,7 @@ module DevCycle
|
|
50
44
|
begin
|
51
45
|
response = Typhoeus.post(
|
52
46
|
@events_api_uri + '/v1/events/batch',
|
53
|
-
headers: { 'Authorization': @sdkKey },
|
47
|
+
headers: { 'Authorization': @sdkKey, 'Content-Type': 'application/json' },
|
54
48
|
body: { 'batch': payload.records }.to_json
|
55
49
|
)
|
56
50
|
if response.code != 201
|
@@ -104,17 +98,4 @@ module DevCycle
|
|
104
98
|
false
|
105
99
|
end
|
106
100
|
end
|
107
|
-
|
108
|
-
# Todo: remove when done testing
|
109
|
-
class FlushTimerTaskObserver
|
110
|
-
def update(time, result, ex)
|
111
|
-
return if ex.nil?
|
112
|
-
|
113
|
-
if ex.is_a?(Concurrent::TimeoutError)
|
114
|
-
print("DVC FlushTimerTaskObserver: Execution timed out")
|
115
|
-
else
|
116
|
-
print("DVC FlushTimerTaskObserver: Execution failed with error: #{ex}")
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
101
|
end
|
@@ -89,7 +89,7 @@ module DevCycle
|
|
89
89
|
@sdkkey = sdkkey
|
90
90
|
@options = options
|
91
91
|
@logger = options.logger
|
92
|
-
|
92
|
+
set_sdk_key_internal(sdkkey)
|
93
93
|
platform_data = PlatformData.new('server', VERSION, RUBY_VERSION, nil, 'Ruby', Socket.gethostname)
|
94
94
|
set_platform_data(platform_data)
|
95
95
|
@configmanager = ConfigManager.new(@sdkkey, self, wait_for_init)
|
@@ -102,12 +102,12 @@ module DevCycle
|
|
102
102
|
|
103
103
|
sig { params(user: UserData).returns(BucketedUserConfig) }
|
104
104
|
def generate_bucketed_config(user)
|
105
|
-
sdkkey_addr = malloc_asc_string(@sdkkey)
|
106
105
|
user_addr = malloc_asc_string(user.to_json)
|
107
106
|
@@stack_tracer = lambda { |message| raise message }
|
108
|
-
config_addr = @@instance.invoke("generateBucketedConfigForUser",
|
107
|
+
config_addr = @@instance.invoke("generateBucketedConfigForUser", @sdkKeyAddr, user_addr)
|
109
108
|
bucketed_config_json = read_asc_string(config_addr)
|
110
109
|
bucketed_config_hash = Oj.load(bucketed_config_json)
|
110
|
+
|
111
111
|
BucketedUserConfig.new(bucketed_config_hash['project'],
|
112
112
|
bucketed_config_hash['environment'],
|
113
113
|
bucketed_config_hash['features'],
|
@@ -119,9 +119,8 @@ module DevCycle
|
|
119
119
|
|
120
120
|
sig { returns(T::Array[EventsPayload]) }
|
121
121
|
def flush_event_queue
|
122
|
-
sdkkey_addr = malloc_asc_string(@sdkkey)
|
123
122
|
@@stack_tracer = lambda { |message| raise message }
|
124
|
-
payload_addr = @@instance.invoke("flushEventQueue",
|
123
|
+
payload_addr = @@instance.invoke("flushEventQueue", @sdkKeyAddr)
|
125
124
|
raw_json = read_asc_string(payload_addr)
|
126
125
|
raw_payloads = Oj.load(raw_json)
|
127
126
|
|
@@ -133,66 +132,69 @@ module DevCycle
|
|
133
132
|
|
134
133
|
sig { returns(Integer) }
|
135
134
|
def check_event_queue_size
|
136
|
-
sdkkey_addr = malloc_asc_string(@sdkkey)
|
137
135
|
@@stack_tracer = lambda { |message| raise message }
|
138
|
-
@@instance.invoke("eventQueueSize",
|
136
|
+
@@instance.invoke("eventQueueSize", @sdkKeyAddr)
|
139
137
|
end
|
140
138
|
|
141
139
|
sig { params(payload_id: String).returns(NilClass) }
|
142
140
|
def on_payload_success(payload_id)
|
143
|
-
sdkkey_addr = malloc_asc_string(@sdkkey)
|
144
141
|
payload_addr = malloc_asc_string(payload_id)
|
145
142
|
@@stack_tracer = lambda { |message| raise message }
|
146
|
-
@@instance.invoke("onPayloadSuccess",
|
143
|
+
@@instance.invoke("onPayloadSuccess", @sdkKeyAddr, payload_addr)
|
147
144
|
end
|
148
145
|
|
149
146
|
sig { params(user: UserData, event: Event).returns(NilClass) }
|
150
147
|
def queue_event(user, event)
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
148
|
+
begin
|
149
|
+
user_addr = malloc_asc_string(Oj.dump(user))
|
150
|
+
asc_pin(user_addr)
|
151
|
+
event_addr = malloc_asc_string(Oj.dump(event))
|
152
|
+
@@stack_tracer = lambda { |message| raise message }
|
153
|
+
@@instance.invoke("queueEvent", @sdkKeyAddr, user_addr, event_addr)
|
154
|
+
ensure
|
155
|
+
asc_unpin(user_addr)
|
156
|
+
end
|
156
157
|
end
|
157
158
|
|
158
159
|
sig { params(event: Event, bucketeduser: T.nilable(BucketedUserConfig)).returns(NilClass) }
|
159
160
|
def queue_aggregate_event(event, bucketeduser)
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
161
|
+
begin
|
162
|
+
variable_variation_map =
|
163
|
+
if !bucketeduser.nil?
|
164
|
+
bucketeduser.variable_variation_map
|
165
|
+
else
|
166
|
+
{}
|
167
|
+
end
|
168
|
+
varmap_addr = malloc_asc_string(Oj.dump(variable_variation_map))
|
169
|
+
asc_pin(varmap_addr)
|
170
|
+
event_addr = malloc_asc_string(Oj.dump(event))
|
171
|
+
@@stack_tracer = lambda { |message| raise message }
|
172
|
+
@@instance.invoke("queueAggregateEvent", @sdkKeyAddr, event_addr, varmap_addr)
|
173
|
+
ensure
|
174
|
+
asc_unpin(varmap_addr)
|
166
175
|
end
|
167
|
-
varmap_addr = malloc_asc_string(Oj.dump(variable_variation_map))
|
168
|
-
event_addr = malloc_asc_string(Oj.dump(event))
|
169
|
-
@@stack_tracer = lambda { |message| raise message }
|
170
|
-
@@instance.invoke("queueAggregateEvent", sdkkey_addr, event_addr, varmap_addr)
|
171
176
|
end
|
172
177
|
|
173
178
|
sig { params(payload_id: String, retryable: Object).returns(NilClass) }
|
174
179
|
def on_payload_failure(payload_id, retryable)
|
175
|
-
sdkkey_addr = malloc_asc_string(@sdkkey)
|
176
180
|
payload_addr = malloc_asc_string(payload_id)
|
177
181
|
@@stack_tracer = lambda { |message| raise message }
|
178
|
-
@@instance.invoke("onPayloadFailure",
|
182
|
+
@@instance.invoke("onPayloadFailure", @sdkKeyAddr, payload_addr, retryable ? 1 : 0)
|
179
183
|
end
|
180
184
|
|
181
|
-
sig { params(
|
182
|
-
def store_config(
|
183
|
-
sdkkey_addr = malloc_asc_string(sdkkey)
|
185
|
+
sig { params(config: String).returns(NilClass) }
|
186
|
+
def store_config(config)
|
184
187
|
config_addr = malloc_asc_string(config)
|
185
188
|
@@stack_tracer = lambda { |message| raise message }
|
186
|
-
@@instance.invoke("setConfigData",
|
189
|
+
@@instance.invoke("setConfigData", @sdkKeyAddr, config_addr)
|
187
190
|
end
|
188
191
|
|
189
192
|
sig { params(options: EventQueueOptions).returns(NilClass) }
|
190
193
|
def init_event_queue(options)
|
191
194
|
options_json = Oj.dump(options)
|
192
|
-
sdkkey_addr = malloc_asc_string(@sdkkey)
|
193
195
|
options_addr = malloc_asc_string(options_json)
|
194
196
|
@@stack_tracer = lambda { |message| raise message }
|
195
|
-
@@instance.invoke("initEventQueue",
|
197
|
+
@@instance.invoke("initEventQueue", @sdkKeyAddr, options_addr)
|
196
198
|
end
|
197
199
|
|
198
200
|
sig { params(customdata: Hash).returns(NilClass) }
|
@@ -213,6 +215,20 @@ module DevCycle
|
|
213
215
|
@@instance.invoke("setPlatformData", platformdata_addr)
|
214
216
|
end
|
215
217
|
|
218
|
+
def set_sdk_key_internal(sdkKey)
|
219
|
+
addr = malloc_asc_string(sdkKey)
|
220
|
+
@sdkKeyAddr = addr
|
221
|
+
asc_pin(addr)
|
222
|
+
end
|
223
|
+
|
224
|
+
def asc_pin(addr)
|
225
|
+
@@instance.invoke("__pin", addr)
|
226
|
+
end
|
227
|
+
|
228
|
+
def asc_unpin(addr)
|
229
|
+
@@instance.invoke("__unpin", addr)
|
230
|
+
end
|
231
|
+
|
216
232
|
# @param [String] string utf8 string to allocate
|
217
233
|
# @return [Integer] address to WASM String
|
218
234
|
sig { params(string: String).returns(Integer) }
|
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.0.
|
4
|
+
version: 2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- DevCycleHQ
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: typhoeus
|
@@ -48,30 +48,30 @@ dependencies:
|
|
48
48
|
name: concurrent-ruby
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
|
-
- -
|
51
|
+
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: 1.2.0
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
|
-
- -
|
58
|
+
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: 1.2.0
|
61
61
|
- !ruby/object:Gem::Dependency
|
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'
|
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'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: oj
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|