promoted-ruby-client 0.1.4 → 0.1.8
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/Gemfile.lock +1 -1
- data/README.md +6 -6
- data/dev.md +2 -3
- data/lib/promoted/ruby/client.rb +87 -37
- data/lib/promoted/ruby/client/faraday_http_client.rb +1 -1
- data/lib/promoted/ruby/client/id_generator.rb +15 -0
- data/lib/promoted/ruby/client/request_builder.rb +34 -8
- data/lib/promoted/ruby/client/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e9911fa22cb387f4258e9261729f5b17baa6412ae2d9ddd82cb943e35c02aef0
|
4
|
+
data.tar.gz: 29a8ae5517ecbdf317671280c31942781b13cf7ba8d6f3f09b9658e3101ee24a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82d1b9721132cc813ddc614292111a0003423c881d836a8dd471115a20b2a2c0b2f0cbdee4d7eb2c12cae993000623012dd21bf8844bd05a9803796f60a99d56
|
7
|
+
data.tar.gz: 91e3466ee73398157ab6b1e41778a89f760aa9741b7a2fcb8c0edb4ad382933ab13a4526145290d70990b4cfa8599c28ca7d0c18d968de50b2aaa81af4768f6c
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -28,10 +28,10 @@ This client will suffice for building log requests. To send actually send traffi
|
|
28
28
|
|
29
29
|
```rb
|
30
30
|
client = Promoted::Ruby::Client::PromotedClient.new({
|
31
|
-
:metrics_endpoint
|
32
|
-
:delivery_endpoint
|
33
|
-
:metrics_api_key
|
34
|
-
:delivery_api_key
|
31
|
+
:metrics_endpoint => "https://<get this from Promoted>",
|
32
|
+
:delivery_endpoint => "https://<get this from Promoted>",
|
33
|
+
:metrics_api_key => "<get this from Promoted>",
|
34
|
+
:delivery_api_key => "<get this from Promoted>"
|
35
35
|
})
|
36
36
|
```
|
37
37
|
|
@@ -88,7 +88,7 @@ Field Name | Type | Optional? | Description
|
|
88
88
|
---------- | ---- | --------- | -----------
|
89
89
|
```:user_info``` | UserInfo | Yes | The user info structure.
|
90
90
|
```:insertion_id``` | String | Yes | Generated by the SDK (*do not set*)
|
91
|
-
```:request_id``` | String | Yes | Generated by the SDK (*do not set*)
|
91
|
+
```:request_id``` | String | Yes | Generated by the SDK when needed (*do not set*)
|
92
92
|
```:content_id``` | String | No | Identifier for the content to be shown, must be set.
|
93
93
|
```:properties``` | Properties | Yes | Any additional custom properties to associate. For v1 integrations, it is fine not to fill in all the properties.
|
94
94
|
|
@@ -101,7 +101,7 @@ A request for content insertions.
|
|
101
101
|
Field Name | Type | Optional? | Description
|
102
102
|
---------- | ---- | --------- | -----------
|
103
103
|
```:user_info``` | UserInfo | Yes | The user info structure.
|
104
|
-
```:request_id``` | String | Yes | Generated by the SDK (*do not set*)
|
104
|
+
```:request_id``` | String | Yes | Generated by the SDK when needed (*do not set*)
|
105
105
|
```:use_case``` | String | Yes | One of the use case values, i.e. 'FEED' (see [constants.rb](https://github.com/promotedai/promoted-ruby-client/blob/main/lib/promoted/ruby/client/constants.rb)).
|
106
106
|
```:properties``` | Properties | Yes | Any additional custom properties to associate.
|
107
107
|
```:paging``` | Paging | Yes | Paging parameters (see TODO)
|
data/dev.md
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
|
2
|
-
## Deploy
|
1
|
+
# Deploy
|
3
2
|
|
4
3
|
1. Update version number.
|
5
4
|
2. Get credentials for deployment from 1password.
|
6
5
|
3. Modify `promoted-ruby-client.gemspec`'s push block.
|
7
6
|
4. Run `gem build promoted-ruby-client.gemspec` to generate `gem`.
|
8
|
-
5. Run (using new output) `gem push promoted-ruby-client-0.1.
|
7
|
+
5. Run (using new output) `gem push promoted-ruby-client-0.1.8.gem`
|
9
8
|
6. Update README with new version.
|
data/lib/promoted/ruby/client.rb
CHANGED
@@ -19,8 +19,16 @@ module Promoted
|
|
19
19
|
class Error < StandardError; end
|
20
20
|
|
21
21
|
attr_reader :perform_checks, :default_only_log, :delivery_timeout_millis, :metrics_timeout_millis, :should_apply_treatment_func,
|
22
|
-
:default_request_headers, :http_client
|
22
|
+
:default_request_headers, :http_client, :logger, :shadow_traffic_delivery_percent, :async_shadow_traffic
|
23
|
+
|
24
|
+
attr_accessor :request_logging_on, :enabled
|
23
25
|
|
26
|
+
##
|
27
|
+
# Whether or not the client is currently enabled for execution.
|
28
|
+
def enabled?
|
29
|
+
@enabled
|
30
|
+
end
|
31
|
+
|
24
32
|
##
|
25
33
|
# A common compact method implementation.
|
26
34
|
def self.copy_and_remove_properties
|
@@ -39,7 +47,8 @@ module Promoted
|
|
39
47
|
@perform_checks = params[:perform_checks]
|
40
48
|
end
|
41
49
|
|
42
|
-
@logger
|
50
|
+
@logger = params[:logger] # Example: Logger.new(STDERR, :progname => "promotedai")
|
51
|
+
@request_logging_on = params[:request_logging_on] || false
|
43
52
|
|
44
53
|
@default_request_headers = params[:default_request_headers] || {}
|
45
54
|
@metrics_api_key = params[:metrics_api_key] || ''
|
@@ -66,21 +75,36 @@ module Promoted
|
|
66
75
|
@http_client = FaradayHTTPClient.new
|
67
76
|
@validator = Promoted::Ruby::Client::Validator.new
|
68
77
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
78
|
+
@async_shadow_traffic = true
|
79
|
+
if params[:async_shadow_traffic] != nil
|
80
|
+
@async_shadow_traffic = params[:async_shadow_traffic] || false
|
81
|
+
end
|
82
|
+
|
83
|
+
@pool = nil
|
84
|
+
if @async_shadow_traffic
|
85
|
+
# Thread pool to process delivery of shadow traffic. Will silently drop excess requests beyond the queue
|
86
|
+
# size, and silently eat errors on the background threads.
|
87
|
+
@pool = Concurrent::ThreadPoolExecutor.new(
|
88
|
+
min_threads: 0,
|
89
|
+
max_threads: 10,
|
90
|
+
max_queue: 100,
|
91
|
+
fallback_policy: :discard
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
95
|
+
@enabled = true
|
96
|
+
if params[:enabled] != nil
|
97
|
+
@enabled = params[:enabled] || false
|
98
|
+
end
|
77
99
|
end
|
78
100
|
|
79
101
|
##
|
80
102
|
# Politely shut down a Promoted client.
|
81
103
|
def close
|
82
|
-
@pool
|
83
|
-
|
104
|
+
if @pool
|
105
|
+
@pool.shutdown
|
106
|
+
@pool.wait_for_termination
|
107
|
+
end
|
84
108
|
end
|
85
109
|
|
86
110
|
##
|
@@ -88,6 +112,14 @@ module Promoted
|
|
88
112
|
def deliver args, headers={}
|
89
113
|
args = Promoted::Ruby::Client::Util.translate_args(args)
|
90
114
|
|
115
|
+
# Respect the enabled state
|
116
|
+
if !@enabled
|
117
|
+
return {
|
118
|
+
insertion: apply_paging(args[:full_insertion], args[:request][:paging])
|
119
|
+
# No log request returned when disabled
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
91
123
|
delivery_request_builder = RequestBuilder.new
|
92
124
|
delivery_request_builder.set_request_params(args)
|
93
125
|
|
@@ -97,7 +129,7 @@ module Promoted
|
|
97
129
|
|
98
130
|
response_insertions = []
|
99
131
|
cohort_membership_to_log = nil
|
100
|
-
|
132
|
+
insertions_from_delivery = false
|
101
133
|
|
102
134
|
only_log = delivery_request_builder.only_log != nil ? delivery_request_builder.only_log : @default_only_log
|
103
135
|
deliver_err = false
|
@@ -117,22 +149,16 @@ module Promoted
|
|
117
149
|
@logger.error("Error calling delivery: " + err.message) if @logger
|
118
150
|
end
|
119
151
|
|
120
|
-
|
152
|
+
insertions_from_delivery = (response != nil && !deliver_err);
|
121
153
|
response_insertions = delivery_request_builder.fill_details_from_response(
|
122
|
-
response ? response[:insertion] :
|
154
|
+
response ? response[:insertion] : [])
|
123
155
|
end
|
124
156
|
end
|
125
157
|
|
126
158
|
request_to_log = nil
|
127
|
-
if !
|
159
|
+
if !insertions_from_delivery then
|
128
160
|
request_to_log = delivery_request_builder.request
|
129
|
-
|
130
|
-
response_insertions = size != nil ? delivery_request_builder.full_insertion[0..size] : delivery_request_builder.full_insertion
|
131
|
-
end
|
132
|
-
|
133
|
-
if request_to_log
|
134
|
-
request_to_log[:request_id] = SecureRandom.uuid if not request_to_log[:request_id]
|
135
|
-
add_missing_ids_on_insertions! request_to_log, response_insertions
|
161
|
+
response_insertions = apply_paging(delivery_request_builder.full_insertion, delivery_request_builder.request[:paging])
|
136
162
|
end
|
137
163
|
|
138
164
|
log_req = nil
|
@@ -156,8 +182,8 @@ module Promoted
|
|
156
182
|
# On a successful delivery request, we don't log the insertions
|
157
183
|
# or the request since they are logged on the server-side.
|
158
184
|
log_req = log_request_builder.log_request_params(
|
159
|
-
include_insertions: !
|
160
|
-
include_request: !
|
185
|
+
include_insertions: !insertions_from_delivery,
|
186
|
+
include_request: !insertions_from_delivery)
|
161
187
|
end
|
162
188
|
|
163
189
|
client_response = {
|
@@ -173,6 +199,12 @@ module Promoted
|
|
173
199
|
def prepare_for_logging args, headers={}
|
174
200
|
args = Promoted::Ruby::Client::Util.translate_args(args)
|
175
201
|
|
202
|
+
if !@enabled
|
203
|
+
return {
|
204
|
+
insertion: args[:full_insertion]
|
205
|
+
}
|
206
|
+
end
|
207
|
+
|
176
208
|
log_request_builder = RequestBuilder.new
|
177
209
|
|
178
210
|
# Note: This method expects as JSON (string keys) but internally, RequestBuilder
|
@@ -210,30 +242,47 @@ module Promoted
|
|
210
242
|
|
211
243
|
private
|
212
244
|
|
245
|
+
def apply_paging full_insertion, paging
|
246
|
+
size = nil
|
247
|
+
if paging
|
248
|
+
size = paging[:size]
|
249
|
+
end
|
250
|
+
return size != nil ? full_insertion[0..size - 1] : full_insertion
|
251
|
+
end
|
252
|
+
|
213
253
|
def send_request payload, endpoint, timeout_millis, api_key, headers={}, send_async=false
|
254
|
+
resp = nil
|
255
|
+
|
214
256
|
headers["x-api-key"] = api_key
|
215
257
|
use_headers = @default_request_headers.merge headers
|
216
258
|
|
217
|
-
if
|
259
|
+
if @request_logging_on && @logger
|
260
|
+
@logger.info("promotedai") {
|
261
|
+
"Sending #{payload.to_json} to #{endpoint}"
|
262
|
+
}
|
263
|
+
end
|
264
|
+
|
265
|
+
if send_async && @pool
|
218
266
|
@pool.post do
|
219
|
-
|
267
|
+
start_time = Time.now.to_i
|
268
|
+
begin
|
269
|
+
resp = @http_client.send(endpoint, timeout_millis, payload, use_headers)
|
270
|
+
rescue Faraday::Error => err
|
271
|
+
@logger.warn("Deliver call failed with #{err}") if @logger
|
272
|
+
return
|
273
|
+
end
|
274
|
+
ellapsed_time = Time.now.to_i - start_time
|
275
|
+
@logger.info("Deliver call completed in #{ellapsed_time} ms") if @logger
|
220
276
|
end
|
221
277
|
else
|
222
278
|
begin
|
223
|
-
@http_client.send(endpoint, timeout_millis, payload, use_headers)
|
279
|
+
resp = @http_client.send(endpoint, timeout_millis, payload, use_headers)
|
224
280
|
rescue Faraday::Error => err
|
225
281
|
raise EndpointError.new(err)
|
226
282
|
end
|
227
283
|
end
|
228
|
-
end
|
229
|
-
|
230
284
|
|
231
|
-
|
232
|
-
insertions.each do |insertion|
|
233
|
-
insertion[:insertion_id] = SecureRandom.uuid if not insertion[:insertion_id]
|
234
|
-
insertion[:session_id] = request[:session_id] if request[:session_id]
|
235
|
-
insertion[:request_id] = request[:request_id] if request[:request_id]
|
236
|
-
end
|
285
|
+
return resp
|
237
286
|
end
|
238
287
|
|
239
288
|
def should_send_as_shadow_traffic?
|
@@ -290,4 +339,5 @@ require "promoted/ruby/client/request_builder"
|
|
290
339
|
require "promoted/ruby/client/sampler"
|
291
340
|
require "promoted/ruby/client/util"
|
292
341
|
require "promoted/ruby/client/validator"
|
293
|
-
require 'securerandom'
|
342
|
+
require 'securerandom'
|
343
|
+
require 'time'
|
@@ -8,7 +8,13 @@ module Promoted
|
|
8
8
|
|
9
9
|
attr_accessor :timing, :user_info, :platform_id
|
10
10
|
|
11
|
-
def initialize
|
11
|
+
def initialize args = {}
|
12
|
+
if args[:id_generator]
|
13
|
+
@id_generator = args[:id_generator]
|
14
|
+
else
|
15
|
+
@id_generator = IdGenerator.new
|
16
|
+
end
|
17
|
+
end
|
12
18
|
|
13
19
|
# Populates request parameters from the given arguments, presumed to be a hash of symbols.
|
14
20
|
def set_request_params args = {}
|
@@ -21,7 +27,6 @@ module Promoted
|
|
21
27
|
@view_id = request[:view_id]
|
22
28
|
@use_case = Promoted::Ruby::Client::USE_CASES[request[:use_case]] || Promoted::Ruby::Client::USE_CASES['UNKNOWN_USE_CASE']
|
23
29
|
@full_insertion = args[:full_insertion]
|
24
|
-
@request_id = SecureRandom.uuid
|
25
30
|
@user_info = request[:user_info] || { :user_id => nil, :log_user_id => nil}
|
26
31
|
@timing = request[:timing] || { :client_log_timestamp => Time.now.to_i }
|
27
32
|
@to_compact_metrics_insertion_func = args[:to_compact_metrics_insertion_func]
|
@@ -48,10 +53,15 @@ module Promoted
|
|
48
53
|
params = {
|
49
54
|
user_info: user_info,
|
50
55
|
timing: timing,
|
51
|
-
|
52
|
-
|
56
|
+
client_info: @client_info.merge({ :client_type => Promoted::Ruby::Client::CLIENT_TYPE['PLATFORM_SERVER'] }),
|
57
|
+
platform_id: @platform_id,
|
58
|
+
view_id: @view_id,
|
59
|
+
session_id: @session_id,
|
60
|
+
use_case: @use_case,
|
61
|
+
search_query: request[:search_query],
|
62
|
+
properties: request[:properties],
|
63
|
+
paging: request[:paging]
|
53
64
|
}
|
54
|
-
params[:request] = request
|
55
65
|
params[:insertion] = should_compact ? compact_delivery_insertions : full_insertion
|
56
66
|
|
57
67
|
params.clean!
|
@@ -88,8 +98,16 @@ module Promoted
|
|
88
98
|
cohort_membership: @experiment,
|
89
99
|
client_info: @client_info
|
90
100
|
}
|
101
|
+
|
102
|
+
request[:request_id] = @id_generator.newID if not request[:request_id]
|
103
|
+
|
104
|
+
# Log request allows for multiple requests but here we only send one.
|
91
105
|
params[:request] = [request] if include_request
|
92
|
-
|
106
|
+
|
107
|
+
if include_insertions
|
108
|
+
params[:insertion] = compact_metrics_insertions if include_insertions
|
109
|
+
add_missing_ids_on_insertions! request, params[:insertion]
|
110
|
+
end
|
93
111
|
|
94
112
|
params.clean!
|
95
113
|
end
|
@@ -120,7 +138,7 @@ module Promoted
|
|
120
138
|
insertion_obj = Hash[insertion_obj]
|
121
139
|
insertion_obj[:user_info] = user_info
|
122
140
|
insertion_obj[:timing] = timing
|
123
|
-
insertion_obj[:insertion_id] =
|
141
|
+
insertion_obj[:insertion_id] = @id_generator.newID
|
124
142
|
insertion_obj[:request_id] = request_id
|
125
143
|
insertion_obj[:position] = offset + index
|
126
144
|
insertion_obj = @to_compact_metrics_insertion_func.call(insertion_obj) if @to_compact_metrics_insertion_func
|
@@ -131,6 +149,14 @@ module Promoted
|
|
131
149
|
|
132
150
|
private
|
133
151
|
|
152
|
+
def add_missing_ids_on_insertions! request, insertions
|
153
|
+
insertions.each do |insertion|
|
154
|
+
insertion[:insertion_id] = @id_generator.newID if not insertion[:insertion_id]
|
155
|
+
insertion[:session_id] = request[:session_id] if request[:session_id]
|
156
|
+
insertion[:request_id] = request[:request_id] if request[:request_id]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
134
160
|
# A list of the response Insertions. This client expects lists to be truncated
|
135
161
|
# already to request.paging.size. If not truncated, this client will truncate
|
136
162
|
# the list.
|
@@ -142,6 +168,6 @@ module Promoted
|
|
142
168
|
end
|
143
169
|
end
|
144
170
|
|
145
|
-
require 'securerandom'
|
146
171
|
require "promoted/ruby/client/constants"
|
147
172
|
require "promoted/ruby/client/extensions"
|
173
|
+
require "promoted/ruby/client/id_generator"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: promoted-ruby-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- scottmcmaster
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -75,6 +75,7 @@ files:
|
|
75
75
|
- lib/promoted/ruby/client/errors.rb
|
76
76
|
- lib/promoted/ruby/client/extensions.rb
|
77
77
|
- lib/promoted/ruby/client/faraday_http_client.rb
|
78
|
+
- lib/promoted/ruby/client/id_generator.rb
|
78
79
|
- lib/promoted/ruby/client/request_builder.rb
|
79
80
|
- lib/promoted/ruby/client/sampler.rb
|
80
81
|
- lib/promoted/ruby/client/util.rb
|