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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 121200a7e00beda3ecf9643712df3aab9794f95719f9f8d65903b9484bf9857d
4
- data.tar.gz: 901e657b2391b76d53d1b50d743469033f50f3679c1919d48c5644621e8c7866
3
+ metadata.gz: e9911fa22cb387f4258e9261729f5b17baa6412ae2d9ddd82cb943e35c02aef0
4
+ data.tar.gz: 29a8ae5517ecbdf317671280c31942781b13cf7ba8d6f3f09b9658e3101ee24a
5
5
  SHA512:
6
- metadata.gz: 54fd3b49e89e049fe39c45afaa10171fc38cf24df7e402e46f922e22e0b12ed6f570f48b0f273b14a7c6a731b98c0d17493ddc4c4636b30582e8a115b0323b92
7
- data.tar.gz: 195b628e077cbb154423aa8156fb16410582885f72ce292ea444c25abc1ca523656bdb65f5632088d593f4579a06f78cbfcd19a17da813095bdd144ad4b91ad9
6
+ metadata.gz: 82d1b9721132cc813ddc614292111a0003423c881d836a8dd471115a20b2a2c0b2f0cbdee4d7eb2c12cae993000623012dd21bf8844bd05a9803796f60a99d56
7
+ data.tar.gz: 91e3466ee73398157ab6b1e41778a89f760aa9741b7a2fcb8c0edb4ad382933ab13a4526145290d70990b4cfa8599c28ca7d0c18d968de50b2aaa81af4768f6c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- promoted-ruby-client (0.1.4)
4
+ promoted-ruby-client (0.1.8)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
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 = "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>"
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.4.gem`
7
+ 5. Run (using new output) `gem push promoted-ruby-client-0.1.8.gem`
9
8
  6. Update README with new version.
@@ -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 = params[:logger] # Example: Logger.new(STDERR, :progname => "promotedai")
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
- # Thread pool to process delivery of shadow traffic. Will silently drop excess requests beyond the queue
70
- # size, and silently eat errors on the background threads.
71
- @pool = Concurrent::ThreadPoolExecutor.new(
72
- min_threads: 0,
73
- max_threads: 10,
74
- max_queue: 100,
75
- fallback_policy: :discard
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.shutdown
83
- @pool.wait_for_termination
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
- insertions_from_promoted = false
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
- insertions_from_promoted = (response != nil && !deliver_err);
152
+ insertions_from_delivery = (response != nil && !deliver_err);
121
153
  response_insertions = delivery_request_builder.fill_details_from_response(
122
- response ? response[:insertion] : nil)
154
+ response ? response[:insertion] : [])
123
155
  end
124
156
  end
125
157
 
126
158
  request_to_log = nil
127
- if !insertions_from_promoted then
159
+ if !insertions_from_delivery then
128
160
  request_to_log = delivery_request_builder.request
129
- size = delivery_request_builder.request.dig(:paging, :size)
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: !insertions_from_promoted,
160
- include_request: !insertions_from_promoted)
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 send_async
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
- @http_client.send(endpoint, timeout_millis, payload, use_headers)
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
- def add_missing_ids_on_insertions! request, insertions
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'
@@ -10,8 +10,8 @@ module Promoted
10
10
  @conn = Faraday.new do |f|
11
11
  f.request :json
12
12
  f.request :retry, max: 3
13
- f.adapter :net_http
14
13
  f.use Faraday::Response::RaiseError # raises on 4xx and 5xx responses
14
+ f.adapter :net_http
15
15
  end
16
16
  end
17
17
 
@@ -0,0 +1,15 @@
1
+ module Promoted
2
+ module Ruby
3
+ module Client
4
+ class IdGenerator
5
+ def initialize;end
6
+
7
+ def newID
8
+ SecureRandom.uuid
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ require 'securerandom'
@@ -8,7 +8,13 @@ module Promoted
8
8
 
9
9
  attr_accessor :timing, :user_info, :platform_id
10
10
 
11
- def initialize;end
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
- cohort_membership: @experiment,
52
- client_info: @client_info.merge({ :client_type => Promoted::Ruby::Client::CLIENT_TYPE['PLATFORM_SERVER'] })
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
- params[:insertion] = compact_metrics_insertions if include_insertions
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] = SecureRandom.uuid # generate random UUID
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"
@@ -1,7 +1,7 @@
1
1
  module Promoted
2
2
  module Ruby
3
3
  module Client
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.8"
5
5
  end
6
6
  end
7
7
  end
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
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-06-30 00:00:00.000000000 Z
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