promoted-ruby-client 0.1.15 → 0.1.16
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|