devcycle-ruby-server-sdk 2.0.1 → 2.0.3
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 +65 -15
- data/lib/devcycle-ruby-server-sdk/localbucketing/config_manager.rb +47 -34
- 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 +54 -36
- data/lib/devcycle-ruby-server-sdk/models/variable.rb +8 -2
- 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: 960c105106387fcb10b360f0befbb77d2dda8c80dce5a51a5eed3c8c49528253
|
4
|
+
data.tar.gz: 1c9274022cece19d953ceba7adfed10cd6418e4a3097ad3305f1a539ace32e23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67cb4a92cb5c9247bd10c838cfa0979d89d331c75c5626967af9b4602c55c30a2842f94f2c15471bb459686382be20432e43bf9951f1c27f516cbc5b2d8a504e
|
7
|
+
data.tar.gz: 802ec0ab8f6b2a7623fe58c94cd007484832c06c5742a38831bebd0991ef2c3b57cc99563ffcee89a545742c0fe1080beea95be01aab88f27983d5d808b359f1
|
@@ -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,13 +56,20 @@ 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)
|
62
|
-
if @
|
63
|
-
|
63
|
+
if @dvc_options.enable_cloud_bucketing
|
64
|
+
raise StandardError.new("Client Custom Data is only available in Local bucketing mode.")
|
65
|
+
end
|
66
|
+
|
67
|
+
if local_bucketing_initialized?
|
68
|
+
@localbucketing.set_client_custom_data(customdata)
|
69
|
+
else
|
70
|
+
@logger.warn("Local bucketing not initialized. Unable to set client custom data.")
|
64
71
|
end
|
65
|
-
|
72
|
+
nil
|
66
73
|
end
|
67
74
|
|
68
75
|
def validate_model(model)
|
@@ -86,7 +93,7 @@ module DevCycle
|
|
86
93
|
return data
|
87
94
|
end
|
88
95
|
|
89
|
-
if local_bucketing_initialized?
|
96
|
+
if local_bucketing_initialized? && @localbucketing.has_config
|
90
97
|
bucketed_config = @localbucketing.generate_bucketed_config(user_data)
|
91
98
|
bucketed_config.features
|
92
99
|
else
|
@@ -169,30 +176,59 @@ module DevCycle
|
|
169
176
|
return data
|
170
177
|
end
|
171
178
|
|
172
|
-
if local_bucketing_initialized?
|
179
|
+
if local_bucketing_initialized? && @localbucketing.has_config
|
173
180
|
bucketed_config = @localbucketing.generate_bucketed_config(user_data)
|
174
181
|
variable_json = bucketed_config.variables[key]
|
175
182
|
if variable_json == nil
|
183
|
+
@logger.warn("No variable found for key #{key}, returning default value")
|
176
184
|
variable_event = Event.new({ type: DevCycle::EventTypes[:agg_variable_defaulted], target: key })
|
177
185
|
@event_queue.queue_aggregate_event(variable_event, bucketed_config)
|
178
186
|
|
179
|
-
return Variable.new({
|
187
|
+
return Variable.new({
|
188
|
+
key: key,
|
189
|
+
type: determine_variable_type(default),
|
190
|
+
value: default,
|
191
|
+
defaultValue: default,
|
192
|
+
isDefaulted: true
|
193
|
+
})
|
180
194
|
end
|
195
|
+
default_type = determine_variable_type(default)
|
196
|
+
variable_type = variable_json['type']
|
197
|
+
if default_type != variable_type
|
198
|
+
@logger.warn("Type mismatch for variable #{key}, returning default value")
|
199
|
+
variable_event = Event.new({ type: DevCycle::EventTypes[:agg_variable_defaulted], target: key })
|
200
|
+
@event_queue.queue_aggregate_event(variable_event, bucketed_config)
|
181
201
|
|
202
|
+
return Variable.new({
|
203
|
+
key: key,
|
204
|
+
type: default_type,
|
205
|
+
value: default,
|
206
|
+
defaultValue: default,
|
207
|
+
isDefaulted: true
|
208
|
+
})
|
209
|
+
end
|
182
210
|
variable_event = Event.new({ type: DevCycle::EventTypes[:agg_variable_evaluated], target: key })
|
183
211
|
@event_queue.queue_aggregate_event(variable_event, bucketed_config)
|
184
212
|
|
185
213
|
Variable.new({
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
214
|
+
key: key,
|
215
|
+
type: variable_type,
|
216
|
+
value: variable_json['value'],
|
217
|
+
defaultValue: default,
|
218
|
+
isDefaulted: false
|
219
|
+
})
|
191
220
|
else
|
221
|
+
@logger.warn("Local bucketing not initialized, returning default value for variable #{key}")
|
192
222
|
variable_event = Event.new({ type: DevCycle::EventTypes[:agg_variable_defaulted], target: key })
|
193
223
|
@event_queue.queue_aggregate_event(variable_event, bucketed_config)
|
194
224
|
|
195
|
-
Variable.new({
|
225
|
+
Variable.new({
|
226
|
+
key: key,
|
227
|
+
type: determine_variable_type(default),
|
228
|
+
value: default,
|
229
|
+
defaultValue: default,
|
230
|
+
isDefaulted: true
|
231
|
+
})
|
196
232
|
end
|
197
233
|
end
|
198
234
|
|
@@ -283,7 +319,7 @@ module DevCycle
|
|
283
319
|
return data
|
284
320
|
end
|
285
321
|
|
286
|
-
if local_bucketing_initialized?
|
322
|
+
if local_bucketing_initialized? && @localbucketing.has_config
|
287
323
|
bucketed_config = @localbucketing.generate_bucketed_config(user_data)
|
288
324
|
bucketed_config.variables
|
289
325
|
else
|
@@ -452,5 +488,19 @@ module DevCycle
|
|
452
488
|
def local_bucketing_initialized?
|
453
489
|
!@localbucketing.nil? && @localbucketing.initialized
|
454
490
|
end
|
491
|
+
|
492
|
+
def determine_variable_type(variable_value)
|
493
|
+
if variable_value.is_a?(String)
|
494
|
+
'String'
|
495
|
+
elsif variable_value.is_a?(TrueClass) || variable_value.is_a?(FalseClass)
|
496
|
+
'Boolean'
|
497
|
+
elsif variable_value.is_a?(Integer) || variable_value.is_a?(Float)
|
498
|
+
'Number'
|
499
|
+
elsif variable_value.is_a?(Hash)
|
500
|
+
'JSON'
|
501
|
+
else
|
502
|
+
raise ArgumentError, "Invalid type for variable: #{variable_value}"
|
503
|
+
end
|
504
|
+
end
|
455
505
|
end
|
456
506
|
end
|
@@ -20,20 +20,33 @@ module DevCycle
|
|
20
20
|
@sdkKey = sdkKey
|
21
21
|
@config_e_tag = ""
|
22
22
|
@logger = local_bucketing.options.logger
|
23
|
+
@polling_enabled = true
|
24
|
+
@max_config_retries = 2
|
23
25
|
|
24
|
-
@config_poller = Concurrent::TimerTask.new(
|
25
|
-
|
26
|
-
execution_interval: @local_bucketing.options.config_polling_interval_ms.fdiv(1000),
|
27
|
-
run_now: true
|
26
|
+
@config_poller = Concurrent::TimerTask.new({
|
27
|
+
execution_interval: @local_bucketing.options.config_polling_interval_ms.fdiv(1000)
|
28
28
|
}) do |task|
|
29
|
-
fetch_config
|
29
|
+
fetch_config
|
30
30
|
end
|
31
31
|
|
32
|
-
t = Thread.new {
|
32
|
+
t = Thread.new { initialize_config }
|
33
33
|
t.join if wait_for_init
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
36
|
+
def initialize_config
|
37
|
+
begin
|
38
|
+
fetch_config
|
39
|
+
@config_poller.execute if @polling_enabled
|
40
|
+
rescue => e
|
41
|
+
@logger.error("DVC Error Initializing Config: #{e.message}")
|
42
|
+
ensure
|
43
|
+
@local_bucketing.initialized = true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def fetch_config
|
48
|
+
return unless @polling_enabled
|
49
|
+
|
37
50
|
req = Typhoeus::Request.new(
|
38
51
|
get_config_url,
|
39
52
|
headers: {
|
@@ -44,25 +57,26 @@ module DevCycle
|
|
44
57
|
req.options[:headers]['If-None-Match'] = @config_e_tag
|
45
58
|
end
|
46
59
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
60
|
+
@max_config_retries.times do
|
61
|
+
resp = req.run
|
62
|
+
case resp.code
|
63
|
+
when 304
|
64
|
+
@logger.debug("Config not modified, using cache, etag: #{this.configEtag}")
|
65
|
+
return
|
66
|
+
when 200
|
67
|
+
set_config(resp.body, resp.headers['Etag'])
|
68
|
+
return
|
69
|
+
when 403
|
70
|
+
stop_polling
|
71
|
+
@logger.error("Failed to download DevCycle config; Invalid SDK Key.")
|
72
|
+
return
|
73
|
+
when 500...599
|
74
|
+
@logger.error("Failed to download DevCycle config. Status: #{resp.code}")
|
75
|
+
else
|
76
|
+
stop_polling
|
77
|
+
@logger.error("Unexpected response code - DevCycle Response: #{Oj.dump(resp)}")
|
78
|
+
return
|
59
79
|
end
|
60
|
-
@logger.warn("Failed to download DevCycle config. Status: #{resp.code}")
|
61
|
-
else
|
62
|
-
if task != nil
|
63
|
-
task.shutdown
|
64
|
-
end
|
65
|
-
raise("Unexpected response code - DevCycle Response: #{Oj.dump(resp)}")
|
66
80
|
end
|
67
81
|
|
68
82
|
nil
|
@@ -73,15 +87,9 @@ module DevCycle
|
|
73
87
|
raise("Invalid JSON body parsed from Config Response")
|
74
88
|
end
|
75
89
|
|
76
|
-
@local_bucketing.store_config(
|
90
|
+
@local_bucketing.store_config(config)
|
77
91
|
@config_e_tag = etag
|
78
|
-
|
79
|
-
if @first_load
|
80
|
-
@logger.info("Config Set. Client Initialized.")
|
81
|
-
@first_load = false
|
82
|
-
@local_bucketing.initialized = true
|
83
|
-
@config_poller.execute
|
84
|
-
end
|
92
|
+
@local_bucketing.has_config = true
|
85
93
|
end
|
86
94
|
|
87
95
|
def get_config_url
|
@@ -89,8 +97,13 @@ module DevCycle
|
|
89
97
|
"#{configBasePath}/config/#{@config_version}/server/#{@sdkKey}.json"
|
90
98
|
end
|
91
99
|
|
100
|
+
def stop_polling
|
101
|
+
@polling_enabled = false
|
102
|
+
@config_poller.shutdown if @config_poller.running?
|
103
|
+
end
|
104
|
+
|
92
105
|
def close
|
93
|
-
@config_poller.shutdown
|
106
|
+
@config_poller.shutdown if @config_poller.running?
|
94
107
|
nil
|
95
108
|
end
|
96
109
|
end
|
@@ -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
|
@@ -14,6 +14,7 @@ module DevCycle
|
|
14
14
|
|
15
15
|
attr_reader :options
|
16
16
|
attr_accessor :initialized
|
17
|
+
attr_accessor :has_config
|
17
18
|
|
18
19
|
@@rand = Random.new(seed = Random.new_seed)
|
19
20
|
@@engine = Wasmtime::Engine.new
|
@@ -86,28 +87,29 @@ module DevCycle
|
|
86
87
|
).void }
|
87
88
|
def initialize(sdkkey, options, wait_for_init)
|
88
89
|
@initialized = false
|
90
|
+
@has_config = false
|
89
91
|
@sdkkey = sdkkey
|
90
92
|
@options = options
|
91
93
|
@logger = options.logger
|
92
|
-
|
94
|
+
set_sdk_key_internal(sdkkey)
|
93
95
|
platform_data = PlatformData.new('server', VERSION, RUBY_VERSION, nil, 'Ruby', Socket.gethostname)
|
94
96
|
set_platform_data(platform_data)
|
95
|
-
@
|
97
|
+
@config_manager = ConfigManager.new(@sdkkey, self, wait_for_init)
|
96
98
|
end
|
97
99
|
|
98
100
|
def close
|
99
|
-
@
|
100
|
-
@
|
101
|
+
@config_manager.close
|
102
|
+
@config_manager = nil
|
101
103
|
end
|
102
104
|
|
103
105
|
sig { params(user: UserData).returns(BucketedUserConfig) }
|
104
106
|
def generate_bucketed_config(user)
|
105
|
-
sdkkey_addr = malloc_asc_string(@sdkkey)
|
106
107
|
user_addr = malloc_asc_string(user.to_json)
|
107
108
|
@@stack_tracer = lambda { |message| raise message }
|
108
|
-
config_addr = @@instance.invoke("generateBucketedConfigForUser",
|
109
|
+
config_addr = @@instance.invoke("generateBucketedConfigForUser", @sdkKeyAddr, user_addr)
|
109
110
|
bucketed_config_json = read_asc_string(config_addr)
|
110
111
|
bucketed_config_hash = Oj.load(bucketed_config_json)
|
112
|
+
|
111
113
|
BucketedUserConfig.new(bucketed_config_hash['project'],
|
112
114
|
bucketed_config_hash['environment'],
|
113
115
|
bucketed_config_hash['features'],
|
@@ -119,9 +121,8 @@ module DevCycle
|
|
119
121
|
|
120
122
|
sig { returns(T::Array[EventsPayload]) }
|
121
123
|
def flush_event_queue
|
122
|
-
sdkkey_addr = malloc_asc_string(@sdkkey)
|
123
124
|
@@stack_tracer = lambda { |message| raise message }
|
124
|
-
payload_addr = @@instance.invoke("flushEventQueue",
|
125
|
+
payload_addr = @@instance.invoke("flushEventQueue", @sdkKeyAddr)
|
125
126
|
raw_json = read_asc_string(payload_addr)
|
126
127
|
raw_payloads = Oj.load(raw_json)
|
127
128
|
|
@@ -133,66 +134,69 @@ module DevCycle
|
|
133
134
|
|
134
135
|
sig { returns(Integer) }
|
135
136
|
def check_event_queue_size
|
136
|
-
sdkkey_addr = malloc_asc_string(@sdkkey)
|
137
137
|
@@stack_tracer = lambda { |message| raise message }
|
138
|
-
@@instance.invoke("eventQueueSize",
|
138
|
+
@@instance.invoke("eventQueueSize", @sdkKeyAddr)
|
139
139
|
end
|
140
140
|
|
141
141
|
sig { params(payload_id: String).returns(NilClass) }
|
142
142
|
def on_payload_success(payload_id)
|
143
|
-
sdkkey_addr = malloc_asc_string(@sdkkey)
|
144
143
|
payload_addr = malloc_asc_string(payload_id)
|
145
144
|
@@stack_tracer = lambda { |message| raise message }
|
146
|
-
@@instance.invoke("onPayloadSuccess",
|
145
|
+
@@instance.invoke("onPayloadSuccess", @sdkKeyAddr, payload_addr)
|
147
146
|
end
|
148
147
|
|
149
148
|
sig { params(user: UserData, event: Event).returns(NilClass) }
|
150
149
|
def queue_event(user, event)
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
150
|
+
begin
|
151
|
+
user_addr = malloc_asc_string(Oj.dump(user))
|
152
|
+
asc_pin(user_addr)
|
153
|
+
event_addr = malloc_asc_string(Oj.dump(event))
|
154
|
+
@@stack_tracer = lambda { |message| raise message }
|
155
|
+
@@instance.invoke("queueEvent", @sdkKeyAddr, user_addr, event_addr)
|
156
|
+
ensure
|
157
|
+
asc_unpin(user_addr)
|
158
|
+
end
|
156
159
|
end
|
157
160
|
|
158
161
|
sig { params(event: Event, bucketeduser: T.nilable(BucketedUserConfig)).returns(NilClass) }
|
159
162
|
def queue_aggregate_event(event, bucketeduser)
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
163
|
+
begin
|
164
|
+
variable_variation_map =
|
165
|
+
if !bucketeduser.nil?
|
166
|
+
bucketeduser.variable_variation_map
|
167
|
+
else
|
168
|
+
{}
|
169
|
+
end
|
170
|
+
varmap_addr = malloc_asc_string(Oj.dump(variable_variation_map))
|
171
|
+
asc_pin(varmap_addr)
|
172
|
+
event_addr = malloc_asc_string(Oj.dump(event))
|
173
|
+
@@stack_tracer = lambda { |message| raise message }
|
174
|
+
@@instance.invoke("queueAggregateEvent", @sdkKeyAddr, event_addr, varmap_addr)
|
175
|
+
ensure
|
176
|
+
asc_unpin(varmap_addr)
|
166
177
|
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
178
|
end
|
172
179
|
|
173
180
|
sig { params(payload_id: String, retryable: Object).returns(NilClass) }
|
174
181
|
def on_payload_failure(payload_id, retryable)
|
175
|
-
sdkkey_addr = malloc_asc_string(@sdkkey)
|
176
182
|
payload_addr = malloc_asc_string(payload_id)
|
177
183
|
@@stack_tracer = lambda { |message| raise message }
|
178
|
-
@@instance.invoke("onPayloadFailure",
|
184
|
+
@@instance.invoke("onPayloadFailure", @sdkKeyAddr, payload_addr, retryable ? 1 : 0)
|
179
185
|
end
|
180
186
|
|
181
|
-
sig { params(
|
182
|
-
def store_config(
|
183
|
-
sdkkey_addr = malloc_asc_string(sdkkey)
|
187
|
+
sig { params(config: String).returns(NilClass) }
|
188
|
+
def store_config(config)
|
184
189
|
config_addr = malloc_asc_string(config)
|
185
190
|
@@stack_tracer = lambda { |message| raise message }
|
186
|
-
@@instance.invoke("setConfigData",
|
191
|
+
@@instance.invoke("setConfigData", @sdkKeyAddr, config_addr)
|
187
192
|
end
|
188
193
|
|
189
194
|
sig { params(options: EventQueueOptions).returns(NilClass) }
|
190
195
|
def init_event_queue(options)
|
191
196
|
options_json = Oj.dump(options)
|
192
|
-
sdkkey_addr = malloc_asc_string(@sdkkey)
|
193
197
|
options_addr = malloc_asc_string(options_json)
|
194
198
|
@@stack_tracer = lambda { |message| raise message }
|
195
|
-
@@instance.invoke("initEventQueue",
|
199
|
+
@@instance.invoke("initEventQueue", @sdkKeyAddr, options_addr)
|
196
200
|
end
|
197
201
|
|
198
202
|
sig { params(customdata: Hash).returns(NilClass) }
|
@@ -213,6 +217,20 @@ module DevCycle
|
|
213
217
|
@@instance.invoke("setPlatformData", platformdata_addr)
|
214
218
|
end
|
215
219
|
|
220
|
+
def set_sdk_key_internal(sdkKey)
|
221
|
+
addr = malloc_asc_string(sdkKey)
|
222
|
+
@sdkKeyAddr = addr
|
223
|
+
asc_pin(addr)
|
224
|
+
end
|
225
|
+
|
226
|
+
def asc_pin(addr)
|
227
|
+
@@instance.invoke("__pin", addr)
|
228
|
+
end
|
229
|
+
|
230
|
+
def asc_unpin(addr)
|
231
|
+
@@instance.invoke("__unpin", addr)
|
232
|
+
end
|
233
|
+
|
216
234
|
# @param [String] string utf8 string to allocate
|
217
235
|
# @return [Integer] address to WASM String
|
218
236
|
sig { params(string: String).returns(Integer) }
|
@@ -220,7 +238,7 @@ module DevCycle
|
|
220
238
|
wasm_object_id = 1
|
221
239
|
@@stack_tracer = lambda { |message| raise message }
|
222
240
|
wasm_new = @@instance.export("__new").to_func
|
223
|
-
utf8_bytes = string.
|
241
|
+
utf8_bytes = string.bytes
|
224
242
|
byte_len = utf8_bytes.length
|
225
243
|
|
226
244
|
start_addr = wasm_new.call(byte_len * 2, wasm_object_id)
|
@@ -27,6 +27,8 @@ module DevCycle
|
|
27
27
|
# Set to true if the Variable could not be fetched
|
28
28
|
attr_accessor :isDefaulted
|
29
29
|
|
30
|
+
attr_accessor :defaultValue
|
31
|
+
|
30
32
|
class EnumAttributeValidator
|
31
33
|
attr_reader :datatype
|
32
34
|
attr_reader :allowable_values
|
@@ -55,6 +57,7 @@ module DevCycle
|
|
55
57
|
:'key' => :'key',
|
56
58
|
:'type' => :'type',
|
57
59
|
:'value' => :'value',
|
60
|
+
:'defaultValue' => :'defaultValue',
|
58
61
|
:'isDefaulted' => :'isDefaulted'
|
59
62
|
}
|
60
63
|
end
|
@@ -70,6 +73,7 @@ module DevCycle
|
|
70
73
|
:'key' => :'String',
|
71
74
|
:'type' => :'String',
|
72
75
|
:'value' => :'Object',
|
76
|
+
:'defaultValue' => :'Object',
|
73
77
|
:'isDefaulted' => :'Boolean'
|
74
78
|
}
|
75
79
|
end
|
@@ -112,6 +116,10 @@ module DevCycle
|
|
112
116
|
else
|
113
117
|
self.isDefaulted = false
|
114
118
|
end
|
119
|
+
|
120
|
+
if attributes.key?(:'defaultValue')
|
121
|
+
self.defaultValue = attributes[:'defaultValue']
|
122
|
+
end
|
115
123
|
end
|
116
124
|
|
117
125
|
# Show invalid properties with the reasons. Usually used together with valid?
|
@@ -296,7 +304,5 @@ module DevCycle
|
|
296
304
|
value
|
297
305
|
end
|
298
306
|
end
|
299
|
-
|
300
307
|
end
|
301
|
-
|
302
308
|
end
|
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.3
|
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-08 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
|