promoted-ruby-client 0.1.15 → 0.1.16
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 +3 -0
- data/dev.md +1 -1
- data/lib/promoted/ruby/client.rb +44 -8
- data/lib/promoted/ruby/client/errors.rb +6 -0
- data/lib/promoted/ruby/client/faraday_http_client.rb +8 -1
- data/lib/promoted/ruby/client/pager.rb +17 -7
- data/lib/promoted/ruby/client/request_builder.rb +4 -1
- data/lib/promoted/ruby/client/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2c2ac1232cfaf7a98ca948a7949a420a6ab311c4b54d92ea8098e8b830e931b
|
4
|
+
data.tar.gz: 9ae8796dc993ecc11e01f1980a2200a7ee10dedb8287504a2bafcebec2f50105
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3df3068c668514c3666435fc1a4b25216223258fd305ba69e4cebf333f5026ff008f868a4bd7f3a15e748bd9b00ddb6dfbb9e0c0de7c72a9ed06ad4a175ddbe
|
7
|
+
data.tar.gz: 7adb59ff3806736008764d32a51176e1a064547259c8f4d7c9d800b4737e688d00b25593c07e5b2ecffc05daad1795830d17efb3f66284d6fc8f02b5045dd1f8
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -17,6 +17,8 @@ More information at [http://www.promoted.ai](http://www.promoted.ai)
|
|
17
17
|
|
18
18
|
### [Faraday](https://github.com/lostisland/faraday)
|
19
19
|
HTTP client for calling Promoted.
|
20
|
+
### [Net::HTTP::Persistent](https://github.com/drbrain/net-http-persistent)
|
21
|
+
Faraday binding (provides connection pool support)
|
20
22
|
### [Concurrent Ruby](https://github.com/ruby-concurrency/concurrent-ruby)
|
21
23
|
Provides a thread pool for making shadow traffic requests to Delivery API in the background on a subset of calls to ```prepare_for_logging```
|
22
24
|
## Creating a Client
|
@@ -50,6 +52,7 @@ Name | Type | Description
|
|
50
52
|
```:default_request_headers``` | Hash | Additional headers to send on the request beyond ```x-api-key```. Defaults to {}
|
51
53
|
```:default_only_log``` | Boolean | If true, the ```deliver``` method will not direct traffic to Delivery API but rather return a request suitable for logging. Defaults to false.
|
52
54
|
```:should_apply_treatment_func``` | Proc | Called during delivery, accepts an experiment and returns a Boolean indicating whether the request should be considered part of the control group (false) or in the experiment (true). If nil, the default behavior of checking the experiement ```:arm``` is applied.
|
55
|
+
```:warmup``` | Boolean | If true, the client will prime the `Net::HTTP::Persistent` connection pool on construction; this can make the first few calls to Promoted complete faster. Defaults to false.
|
53
56
|
|
54
57
|
## Data Types
|
55
58
|
|
data/dev.md
CHANGED
@@ -4,5 +4,5 @@
|
|
4
4
|
2. Get credentials for deployment from 1password.
|
5
5
|
3. Modify `promoted-ruby-client.gemspec`'s push block.
|
6
6
|
4. Run `gem build promoted-ruby-client.gemspec` to generate `gem`.
|
7
|
-
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.16.gem`
|
8
8
|
6. Update README with new version.
|
data/lib/promoted/ruby/client.rb
CHANGED
@@ -73,7 +73,7 @@ module Promoted
|
|
73
73
|
@delivery_timeout_millis = params[:delivery_timeout_millis] || DEFAULT_DELIVERY_TIMEOUT_MILLIS
|
74
74
|
@metrics_timeout_millis = params[:metrics_timeout_millis] || DEFAULT_METRICS_TIMEOUT_MILLIS
|
75
75
|
|
76
|
-
@http_client = FaradayHTTPClient.new
|
76
|
+
@http_client = FaradayHTTPClient.new(@logger)
|
77
77
|
@validator = Promoted::Ruby::Client::Validator.new
|
78
78
|
|
79
79
|
@async_shadow_traffic = true
|
@@ -97,6 +97,10 @@ module Promoted
|
|
97
97
|
if params[:enabled] != nil
|
98
98
|
@enabled = params[:enabled] || false
|
99
99
|
end
|
100
|
+
|
101
|
+
if params[:warmup]
|
102
|
+
do_warmup
|
103
|
+
end
|
100
104
|
end
|
101
105
|
|
102
106
|
##
|
@@ -109,7 +113,7 @@ module Promoted
|
|
109
113
|
end
|
110
114
|
|
111
115
|
##
|
112
|
-
# Make a delivery request.
|
116
|
+
# Make a delivery request. If @perform_checks is set, input validation will occur and possibly raise errors.
|
113
117
|
def deliver args, headers={}
|
114
118
|
args = Promoted::Ruby::Client::Util.translate_args(args)
|
115
119
|
|
@@ -124,7 +128,16 @@ module Promoted
|
|
124
128
|
delivery_request_builder = RequestBuilder.new
|
125
129
|
delivery_request_builder.set_request_params(args)
|
126
130
|
|
127
|
-
|
131
|
+
# perform_checks raises errors.
|
132
|
+
if @perform_checks
|
133
|
+
perform_common_checks!(args)
|
134
|
+
|
135
|
+
if args[:insertion_page_type] == Promoted::Ruby::Client::INSERTION_PAGING_TYPE['PRE_PAGED'] then
|
136
|
+
err = DeliveryInsertionPageType.new
|
137
|
+
@logger.error(err) if @logger
|
138
|
+
raise err
|
139
|
+
end
|
140
|
+
end
|
128
141
|
|
129
142
|
delivery_request_builder.ensure_client_timestamp
|
130
143
|
|
@@ -135,10 +148,15 @@ module Promoted
|
|
135
148
|
only_log = delivery_request_builder.only_log != nil ? delivery_request_builder.only_log : @default_only_log
|
136
149
|
deliver_err = false
|
137
150
|
|
138
|
-
|
151
|
+
begin
|
152
|
+
@pager.validate_paging(delivery_request_builder.full_insertion, delivery_request_builder.request[:paging])
|
153
|
+
rescue InvalidPagingError => err
|
139
154
|
# Invalid input, log and do SDK-side delivery.
|
140
|
-
@logger.warn(
|
141
|
-
|
155
|
+
@logger.warn(err) if @logger
|
156
|
+
return {
|
157
|
+
insertion: err.default_insertions_page
|
158
|
+
# No log request returned when no response insertions due to invalid paging
|
159
|
+
}
|
142
160
|
end
|
143
161
|
|
144
162
|
if !only_log
|
@@ -248,6 +266,22 @@ module Promoted
|
|
248
266
|
|
249
267
|
private
|
250
268
|
|
269
|
+
def do_warmup
|
270
|
+
if !@delivery_endpoint
|
271
|
+
# Warmup only supported when delivery is enabled.
|
272
|
+
return
|
273
|
+
end
|
274
|
+
|
275
|
+
warmup_url = @delivery_endpoint.reverse.sub("/deliver".reverse, "/healthz".reverse).reverse
|
276
|
+
@logger.info("Warming up at #{warmup_url}") if @logger
|
277
|
+
1.upto(20) do
|
278
|
+
resp = @http_client.get(warmup_url)
|
279
|
+
if resp != "ok"
|
280
|
+
@logger.warn("Got a failure warming up") if @logger
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
251
285
|
def send_request payload, endpoint, timeout_millis, api_key, headers={}, send_async=false
|
252
286
|
resp = nil
|
253
287
|
|
@@ -305,8 +339,9 @@ module Promoted
|
|
305
339
|
|
306
340
|
# Call Delivery API and log/ignore errors.
|
307
341
|
start_time = Time.now
|
342
|
+
response = nil
|
308
343
|
begin
|
309
|
-
send_request(delivery_request_params, @delivery_endpoint, @delivery_timeout_millis, @delivery_api_key, headers, @async_shadow_traffic)
|
344
|
+
response = send_request(delivery_request_params, @delivery_endpoint, @delivery_timeout_millis, @delivery_api_key, headers, @async_shadow_traffic)
|
310
345
|
rescue StandardError => err
|
311
346
|
@logger.warn("Shadow traffic call failed with #{err}") if @logger
|
312
347
|
return
|
@@ -314,7 +349,8 @@ module Promoted
|
|
314
349
|
|
315
350
|
if !@async_shadow_traffic
|
316
351
|
ellapsed_time = Time.now - start_time
|
317
|
-
|
352
|
+
insertions = response ? response[:insertion] : []
|
353
|
+
@logger.info("Shadow traffic call completed in #{ellapsed_time.to_f * 1000} ms with #{insertions.length} insertions") if @logger
|
318
354
|
end
|
319
355
|
end
|
320
356
|
|
@@ -6,10 +6,13 @@ module Promoted
|
|
6
6
|
module Client
|
7
7
|
class FaradayHTTPClient
|
8
8
|
|
9
|
-
def initialize
|
9
|
+
def initialize(logger = nil)
|
10
10
|
@conn = Faraday.new do |f|
|
11
11
|
f.request :json
|
12
12
|
f.request :retry, max: 3
|
13
|
+
if logger
|
14
|
+
f.response :logger, logger, { headers: false, bodies: true, log_level: :debug }
|
15
|
+
end
|
13
16
|
f.use Faraday::Response::RaiseError # raises on 4xx and 5xx responses
|
14
17
|
f.adapter :net_http_persistent
|
15
18
|
end
|
@@ -30,6 +33,10 @@ module Promoted
|
|
30
33
|
response.body
|
31
34
|
end
|
32
35
|
end
|
36
|
+
|
37
|
+
def get(endpoint)
|
38
|
+
@conn.get(endpoint).body
|
39
|
+
end
|
33
40
|
end
|
34
41
|
end
|
35
42
|
end
|
@@ -1,18 +1,28 @@
|
|
1
1
|
module Promoted
|
2
2
|
module Ruby
|
3
3
|
module Client
|
4
|
+
class InvalidPagingError < StandardError
|
5
|
+
attr_reader :default_insertions_page
|
6
|
+
|
7
|
+
def initialize(message, default_insertions_page)
|
8
|
+
super(message)
|
9
|
+
@default_insertions_page = default_insertions_page
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
4
13
|
class Pager
|
5
14
|
def validate_paging (insertions, paging)
|
6
|
-
if paging && paging[:offset]
|
7
|
-
|
15
|
+
if paging && paging[:offset] && paging[:offset] >= insertions.length
|
16
|
+
raise InvalidPagingError.new("Invalid page offset (insertion size #{insertions.length}, offset #{paging[:offset]})", [])
|
8
17
|
end
|
9
|
-
return true
|
10
18
|
end
|
11
19
|
|
12
20
|
def apply_paging (insertions, insertion_page_type, paging = nil)
|
13
|
-
|
14
|
-
|
15
|
-
|
21
|
+
begin
|
22
|
+
validate_paging(insertions, paging)
|
23
|
+
rescue InvalidPagingError => err
|
24
|
+
# This is invalid input, stop it before it goes to the server.
|
25
|
+
return err.default_insertions_page
|
16
26
|
end
|
17
27
|
|
18
28
|
if !paging
|
@@ -54,4 +64,4 @@ module Promoted
|
|
54
64
|
end
|
55
65
|
end
|
56
66
|
end
|
57
|
-
end
|
67
|
+
end
|
@@ -99,10 +99,13 @@ module Promoted
|
|
99
99
|
params = {
|
100
100
|
user_info: user_info,
|
101
101
|
timing: timing,
|
102
|
-
cohort_membership: @experiment,
|
103
102
|
client_info: @client_info
|
104
103
|
}
|
105
104
|
|
105
|
+
if @experiment
|
106
|
+
params[:cohort_membership] = [@experiment]
|
107
|
+
end
|
108
|
+
|
106
109
|
# Log request allows for multiple requests but here we only send one.
|
107
110
|
if include_request
|
108
111
|
request[:request_id] = request[:request_id] || @id_generator.newID
|
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.16
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- scottmcmaster
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-07-
|
11
|
+
date: 2021-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -167,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
167
|
- !ruby/object:Gem::Version
|
168
168
|
version: '0'
|
169
169
|
requirements: []
|
170
|
-
rubygems_version: 3.
|
170
|
+
rubygems_version: 3.2.24
|
171
171
|
signing_key:
|
172
172
|
specification_version: 4
|
173
173
|
summary: A Ruby Client to contact Promoted APIs.
|