determinator 2.3.1 → 2.5.0

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: '08378908b45b61bc3c88232e1e480db1200acfe98d3b42dfd10e27420067b5e8'
4
- data.tar.gz: ee822d9401d3c8a0019ae45ecdebd1f2becd56e7081764dd92ecbba9a30b6fa5
3
+ metadata.gz: b505247b6902fb3768389da7b5a20e625f95e5ccaec778ae7fb52e1808286b73
4
+ data.tar.gz: 659b93e86df258535f904bd90d91768767c5c1644cd578d3efe3f45a9c2aba6f
5
5
  SHA512:
6
- metadata.gz: '0288df451ba45366adfb9ffb1f76147c0e565ee647d278f00b23877490cdbb7ebd4fd1b832e46f3812616894d576ee285f509df67e54a68a69415ce6370bfc65'
7
- data.tar.gz: 93cc9692b60bc97bfcf629995bfd38afdbf00161864bec8b5b15568a0b409470d17b52ad1673270444afd7080ff857b10605cea4c0d733b41fbb633a8bf13dd5
6
+ metadata.gz: 753968e66ac00b3f0606eed33b5d1873ad23a89cce901b69e261f38263ff14f18b975a0f03e55146e8ea78dc397b1a48878f10c3b1fc6eadd4f278a78f2a7703
7
+ data.tar.gz: 46d183bc1e87d5031b43115bb63573503725f441a44603577274fef9817cd20722471bcba1b46d018beab4828bbcbf738c4de742aff0de26578178330edd2885
@@ -10,6 +10,10 @@ jobs:
10
10
  steps:
11
11
  - checkout
12
12
 
13
+ - run:
14
+ name: Install bundler
15
+ command: gem install bundler -v 2.1.4
16
+
13
17
  - run:
14
18
  name: Bundle Install
15
19
  command: bundle install
@@ -30,6 +34,10 @@ jobs:
30
34
  steps:
31
35
  - checkout
32
36
 
37
+ - run:
38
+ name: Install bundler
39
+ command: gem install bundler -v 2.1.4
40
+
33
41
  - run:
34
42
  name: Bundle Install
35
43
  command: bundle install
@@ -50,6 +58,10 @@ jobs:
50
58
  steps:
51
59
  - checkout
52
60
 
61
+ - run:
62
+ name: Install bundler
63
+ command: gem install bundler -v 2.1.4
64
+
53
65
  - run:
54
66
  name: Bundle Install
55
67
  command: bundle install
@@ -1,3 +1,39 @@
1
+ # 2.5.0
2
+
3
+ Feature:
4
+ - Add fixed determinations
5
+
6
+ # 2.4.4
7
+
8
+ Bug fix:
9
+ - Count repeated determinations instead of tracking separately
10
+
11
+ # 2.4.3
12
+
13
+ Feature:
14
+ - Add Sinatra endpoint tracking
15
+
16
+ Bug fix:
17
+ - Remove endpoint tracking of PATH_INFO
18
+
19
+ # 2.4.2
20
+
21
+ Feature:
22
+ - Add endpoint information to tracking request
23
+
24
+ Bug fix:
25
+ - Make tracking request "start" attribute an actual time
26
+
27
+ # 2.4.1
28
+
29
+ Bug fix:
30
+ - Update "fake" retrievers to match behaviour introduced in `v2.3.1` when a feature is missing
31
+
32
+ # 2.4.0
33
+
34
+ Feature:
35
+ - Add tracker middleware
36
+
1
37
  # v2.3.1 (2019-05-25)
2
38
 
3
39
  Feature:
data/README.md CHANGED
@@ -204,7 +204,7 @@ variant = determinator.which_variant(
204
204
  app_version: "1.2.3"
205
205
  }
206
206
  )
207
- ```
207
+ ```
208
208
  The `app_version` constraint for that flag needs to follow ruby gem version constraints. We support the following operators: `>, <, >=, <=, ~>`. For example:
209
209
  `app_version: ">=1.2.0"`
210
210
 
@@ -220,6 +220,8 @@ Determinator.configure(retrieval: nil)
220
220
 
221
221
  * Tag your rspec test with `:determinator_support`, so the `forced_determination` helper method will be available.
222
222
 
223
+ Please note, `RSpec::Determinator` mocks a determination _outcome_, not the process of choosing one. Set the `only_for` argument to be the properties you require for Determinator to return the specified outcome. At the moment this mock does not allow for the testing of the `id` or `guid` arguments (only the properties).
224
+
223
225
  ```ruby
224
226
  RSpec.describe "something", :determinator_support do
225
227
 
@@ -251,6 +253,73 @@ end
251
253
 
252
254
  * Check out [the specs for `RSpec::Determinator`](spec/rspec/determinator_spec.rb) to find out what you can do!
253
255
 
256
+ ## Tracking
257
+
258
+ The library includes a middleware to track all determinations being made, allowing logging them at the end of the request
259
+ (including some useful request metrics).
260
+
261
+ To enable it, e.g. in Rails:
262
+
263
+ ```ruby
264
+ # config/application.rb
265
+
266
+ require 'determinator/tracking/rack/middleware'
267
+
268
+ # possibly near the top of your stack, in case other middlewares make determinations
269
+ config.middleware.use Determinator::Tracking::Rack::Middleware
270
+ ```
271
+
272
+ or for Sidekiq:
273
+
274
+ ```ruby
275
+ # config/initializers/sidekiq.rb
276
+
277
+ require 'determinator/tracking/sidekiq/middleware'
278
+
279
+ Sidekiq.configure_server do |config|
280
+ config.server_middleware do |chain|
281
+ chain.add Determinator::Tracking::Sidekiq::Middleware
282
+ end
283
+ end
284
+ ```
285
+
286
+ ```ruby
287
+ # config/initializers/determinator.rb
288
+
289
+ require 'determinator/tracking'
290
+
291
+ Determinator::Tracking.on_request do |r|
292
+ Rails.logger.info("tag=determinator_request endpoint=#{r.endpoint} type=#{r.type} request_time=#{r.time} error=#{r.error?} response_status=#{r.attributes[:status]} sidekiq_queue=#{r.attributes[:queue]}")
293
+ r.determinations.each do |d|
294
+ Rails.logger.info("tag=determination id=#{d.id} guid=#{d.guid} flag=#{d.feature_id} result=#{d.determination}")
295
+ end
296
+ end
297
+
298
+ # The library sets the "endpoint" with information about the request or sidekiq job. If you
299
+ # have environment variables that further identify the service, e.g. ENV['APP_NAME'],
300
+ # you can configure the tracker to prepend it to the endpoint:
301
+ Determinator::Tracking.endpoint_env_vars = ['APP_NAME']
302
+
303
+ # If using an APM, you can provide trace information on the request by providing a get_context hook: e.g.
304
+
305
+ Determinator::Tracking.get_context do
306
+ span = Datadog.tracer.active_root_span
307
+ return unless span
308
+ Determinator::Tracking::Context.new(
309
+ request_id: span.trace_id,
310
+ service: span.service,
311
+ resource: span.resource,
312
+ type: span.type,
313
+ meta: span.meta
314
+ )
315
+ end
316
+ ```
317
+
318
+ NOTE: determinations will only be recorded on the threads where Determinator::Tracking is initialised via the middleware. If offloading work away from these thread (for example, by spinning up new threads within a Rack request or a Sidekiq worker), make the determinations before, and pass them through to the new threads; or, if it's not possible, collect them manually and track them in the request's thread with
319
+ ```
320
+ Determinator::Tracking.track(id, guid, feature, determination)
321
+ ```
322
+
254
323
  ## Testing this library
255
324
 
256
325
  This library makes use of the [Determinator Standard Tests](https://github.com/deliveroo/determinator-standard-tests) to ensure that it conforms to the same specification as determinator libraries in other languages. The standard tests can be updated to the latest ones available by updating the submodule:
@@ -23,11 +23,12 @@ Gem::Specification.new do |spec|
23
23
  spec.add_runtime_dependency "faraday"
24
24
  spec.add_runtime_dependency "semantic", "~> 1.6"
25
25
 
26
- spec.add_development_dependency "bundler", "~> 1.13"
26
+ spec.add_development_dependency "bundler", "~> 2.1.4"
27
27
  spec.add_development_dependency "rake", "~> 10.0"
28
28
  spec.add_development_dependency "rspec", "~> 3.0"
29
29
  spec.add_development_dependency "rspec-its", "~> 1.2"
30
30
  spec.add_development_dependency "guard-rspec", "~> 4.7"
31
31
  spec.add_development_dependency "factory_girl", "~> 4.8"
32
32
  spec.add_development_dependency 'webmock'
33
+ spec.add_development_dependency "sidekiq"
33
34
  end
@@ -2,10 +2,12 @@ require 'determinator/version'
2
2
  require 'determinator/control'
3
3
  require 'determinator/feature'
4
4
  require 'determinator/target_group'
5
+ require 'determinator/fixed_determination'
5
6
  require 'determinator/cache/fetch_wrapper'
6
7
  require 'determinator/serializers/json'
7
8
  require 'determinator/missing_response'
8
9
  require 'determinator/error_response'
10
+ require 'determinator/tracking'
9
11
 
10
12
 
11
13
  module Determinator
@@ -83,6 +85,7 @@ module Determinator
83
85
  end
84
86
 
85
87
  def notice_determination(id, guid, feature, determination)
88
+ Determinator::Tracking.track(id, guid, feature, determination)
86
89
  return unless @determination_callback
87
90
  @determination_callback.call(id, guid, feature, determination)
88
91
  end
@@ -81,6 +81,14 @@ module Determinator
81
81
 
82
82
  return feature.override_value_for(id) if feature.overridden_for?(id)
83
83
 
84
+ fixed_determination = choose_fixed_determination(feature, properties)
85
+ # Given constraints have specified that this actor's determination should be fixed
86
+ if fixed_determination
87
+ return false unless fixed_determination.feature_on
88
+ return true unless feature.experiment?
89
+ return fixed_determination.variant
90
+ end
91
+
84
92
  target_group = choose_target_group(feature, properties)
85
93
  # Given constraints have excluded this actor from this experiment
86
94
  return false unless target_group
@@ -106,23 +114,34 @@ module Determinator
106
114
  false
107
115
  end
108
116
 
117
+ def choose_fixed_determination(feature, properties)
118
+ # Keys and values must be strings
119
+ normalised_properties = normalise_properties(properties)
120
+
121
+ feature.fixed_determinations.find { |fd|
122
+ matches_constraints(normalised_properties, fd.constraints)
123
+ }
124
+ end
125
+
109
126
  def choose_target_group(feature, properties)
110
127
  # Keys and values must be strings
111
- normalised_properties = properties.each_with_object({}) do |(name, values), hash|
112
- hash[name.to_s] = [*values].map(&:to_s)
113
- end
128
+ normalised_properties = normalise_properties(properties)
114
129
 
115
130
  feature.target_groups.select { |tg|
116
131
  next false unless tg.rollout.between?(1, 65_536)
117
132
 
118
- tg.constraints.reduce(true) do |fit, (scope, *required)|
119
- present = [*normalised_properties[scope]]
120
- fit && matches_requirements?(scope, required, present)
121
- end
133
+ matches_constraints(normalised_properties, tg.constraints)
122
134
  # Must choose target group deterministically, if more than one match
123
135
  }.sort_by { |tg| tg.rollout }.last
124
136
  end
125
137
 
138
+ def matches_constraints(normalised_properties, constraints)
139
+ constraints.reduce(true) do |fit, (scope, *required)|
140
+ present = [*normalised_properties[scope]]
141
+ fit && matches_requirements?(scope, required, present)
142
+ end
143
+ end
144
+
126
145
  def matches_requirements?(scope, required, present)
127
146
  case scope
128
147
  when "app_version" then has_any_app_version?(required, present)
@@ -205,5 +224,13 @@ module Determinator
205
224
 
206
225
  raise ArgumentError, "A variant should have been found by this point, there is a bug in the code."
207
226
  end
227
+
228
+ private
229
+
230
+ def normalise_properties(properties)
231
+ properties.each_with_object({}) do |(name, values), hash|
232
+ hash[name.to_s] = [*values].map(&:to_s)
233
+ end
234
+ end
208
235
  end
209
236
  end
@@ -3,13 +3,14 @@ module Determinator
3
3
  #
4
4
  # @attr_reader [nil,Hash<String,Integer>] variants The variants for this experiment, with the name of the variant as the key and the weight as the value. Will be nil for non-experiments.
5
5
  class Feature
6
- attr_reader :name, :identifier, :bucket_type, :variants, :target_groups, :active, :winning_variant
6
+ attr_reader :name, :identifier, :bucket_type, :variants, :target_groups, :fixed_determinations, :active, :winning_variant
7
7
 
8
- def initialize(name:, identifier:, bucket_type:, target_groups:, variants: {}, overrides: {}, active: false, winning_variant: nil)
8
+ def initialize(name:, identifier:, bucket_type:, target_groups:, fixed_determinations: [], variants: {}, overrides: {}, active: false, winning_variant: nil)
9
9
  @name = name.to_s
10
- @identifier = (identifier || name).to_s
10
+ @identifier = identifier.to_s
11
11
  @variants = variants
12
12
  @target_groups = parse_target_groups(target_groups)
13
+ @fixed_determinations = parse_fixed_determinations(fixed_determinations)
13
14
  @winning_variant = parse_outcome(winning_variant, allow_exclusion: false)
14
15
  @active = active
15
16
  @bucket_type = bucket_type.to_sym
@@ -72,14 +73,43 @@ module Determinator
72
73
 
73
74
  TargetGroup.new(
74
75
  rollout: target_group['rollout'].to_i,
75
- constraints: constraints.each_with_object({}) do |(key, value), hash|
76
- hash[key.to_s] = [*value].map(&:to_s)
77
- end
76
+ constraints: parse_constraints(constraints)
78
77
  )
79
78
 
80
79
  # Invalid target groups are ignored
81
80
  rescue
82
81
  nil
83
82
  end
83
+
84
+ def parse_fixed_determinations(fixed_determinations)
85
+ fixed_determinations.map(&method(:parse_fixed_determination)).compact
86
+ end
87
+
88
+ def parse_fixed_determination(fixed_determination)
89
+ return fixed_determination if fixed_determination.is_a? FixedDetermination
90
+
91
+ variant = fixed_determination['variant']
92
+ return nil if variant && !variants.keys.include?(variant)
93
+
94
+ # if a variant is present the fixed determination should always be on
95
+ return nil if variant && !fixed_determination['feature_on']
96
+
97
+ constraints = fixed_determination['constraints'].to_h
98
+
99
+ FixedDetermination.new(
100
+ feature_on: fixed_determination['feature_on'],
101
+ variant: variant,
102
+ constraints: parse_constraints(constraints)
103
+ )
104
+ # Invalid fixed determinations are ignored
105
+ rescue
106
+ nil
107
+ end
108
+
109
+ def parse_constraints(constraints)
110
+ constraints.each_with_object({}) do |(key, value), hash|
111
+ hash[key.to_s] = [*value].map(&:to_s)
112
+ end
113
+ end
84
114
  end
85
115
  end
@@ -0,0 +1,20 @@
1
+ module Determinator
2
+ class FixedDetermination
3
+ attr_reader :feature_on, :variant, :constraints
4
+
5
+ def initialize(feature_on:, variant:, constraints: {})
6
+ @feature_on = feature_on
7
+ @variant = variant
8
+ @constraints = constraints
9
+ end
10
+
11
+ def inspect
12
+ "<feature_on: #{feature_on}, variant: #{variant}, constraints: #{constraints}"
13
+ end
14
+
15
+ def ==(other)
16
+ return false unless other.is_a?(self.class)
17
+ other.feature_on == feature_on && other.variant == variant && other.constraints == constraints
18
+ end
19
+ end
20
+ end
@@ -10,7 +10,7 @@ module Determinator
10
10
 
11
11
  # @param name [string,symbol] The name of the feature to retrieve
12
12
  def retrieve(name)
13
- @features[name.to_s]
13
+ @features.fetch(name.to_s, MissingResponse.new)
14
14
  end
15
15
 
16
16
  # @param feature [Determinator::Feature] The feature to store
@@ -10,6 +10,7 @@ module Determinator
10
10
  # The Control class will assume a nil return from this method
11
11
  # means the feature doesn't exist, so in turn will return `false`.
12
12
  def retrieve(_)
13
+ MissingResponse.new
13
14
  end
14
15
  end
15
16
  end
@@ -12,14 +12,15 @@ module Determinator
12
12
  obj = string_or_hash.is_a?(Hash) ? string_or_hash : ::JSON.parse(string_or_hash)
13
13
 
14
14
  Determinator::Feature.new(
15
- name: obj['name'],
16
- identifier: obj['identifier'],
17
- bucket_type: obj['bucket_type'],
18
- active: (obj['active'] === true),
19
- target_groups: obj['target_groups'],
20
- variants: obj['variants'].to_h,
21
- overrides: obj['overrides'].to_h,
22
- winning_variant: obj['winning_variant'].to_s,
15
+ name: obj['name'],
16
+ identifier: obj['identifier'],
17
+ bucket_type: obj['bucket_type'],
18
+ active: (obj['active'] === true),
19
+ target_groups: obj['target_groups'],
20
+ fixed_determinations: obj['fixed_determinations'].to_a,
21
+ variants: obj['variants'].to_h,
22
+ overrides: obj['overrides'].to_h,
23
+ winning_variant: obj['winning_variant'].to_s,
23
24
  )
24
25
  end
25
26
  end
@@ -0,0 +1,74 @@
1
+ require 'determinator/tracking/tracker'
2
+ require 'determinator/tracking/context'
3
+
4
+ module Determinator
5
+ module Tracking
6
+ class << self
7
+ attr_reader :endpoint_env_vars
8
+
9
+ def instance
10
+ Thread.current[:determinator_tracker]
11
+ end
12
+
13
+ def start!(type)
14
+ Thread.current[:determinator_tracker] = Tracker.new(type)
15
+ end
16
+
17
+ def finish!(endpoint:, error:, **attributes)
18
+ return false unless started?
19
+ request = instance.finish!(endpoint: endpoint, error: error, **attributes)
20
+ clear!
21
+ report(request)
22
+ request
23
+ end
24
+
25
+ def clear!
26
+ Thread.current[:determinator_tracker] = nil
27
+ end
28
+
29
+ def started?
30
+ !!instance
31
+ end
32
+
33
+ def track(id, guid, feature, determination)
34
+ return false unless started?
35
+ instance.track(id, guid, feature, determination)
36
+ end
37
+
38
+ def on_request(&block)
39
+ @on_request = block
40
+ end
41
+
42
+ def report(request)
43
+ return unless @on_request
44
+ @on_request.call(request)
45
+ end
46
+
47
+ def get_context(&block)
48
+ @get_context = block
49
+ end
50
+
51
+ def context
52
+ return unless @get_context
53
+ @get_context.call
54
+ rescue
55
+ nil
56
+ end
57
+
58
+ def clear_hooks!
59
+ @on_request = nil
60
+ @get_context = nil
61
+ end
62
+
63
+ def endpoint_env_vars=(vars)
64
+ @endpoint_env_vars = Array(vars)
65
+ end
66
+
67
+ def collect_endpoint_info(parts)
68
+ endpoint = Array(Determinator::Tracking.endpoint_env_vars).map{ |v| ENV[v] }
69
+ endpoint += Array(parts)
70
+ endpoint.reject{ |p| p.nil? || p == ''}.join(' ')
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,15 @@
1
+ module Determinator
2
+ module Tracking
3
+ class Context
4
+ attr_reader :request_id, :service, :resource
5
+
6
+ def initialize(request_id: nil, service: nil, resource: nil, type: nil, meta: {})
7
+ @request_id = request_id
8
+ @service = service
9
+ @resource = resource
10
+ @type = type
11
+ @meta = meta
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ module Determinator
2
+ module Tracking
3
+ class Determination
4
+ attr_reader :id, :guid, :feature_id, :determination
5
+
6
+ def initialize(id:, guid:, feature_id:, determination:)
7
+ @id = id
8
+ @guid = guid
9
+ @feature_id = feature_id
10
+ @determination = determination
11
+ end
12
+
13
+ def ==(other)
14
+ id == other.id && guid == other.guid && feature_id == other.feature_id && determination == other.determination
15
+ end
16
+
17
+ alias eql? ==
18
+
19
+ def hash
20
+ [id, guid, feature_id, determination].hash
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,43 @@
1
+ require 'determinator/tracking'
2
+
3
+ module Determinator
4
+ module Tracking
5
+ module Rack
6
+ class Middleware
7
+ def initialize(app)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ Determinator::Tracking.start!(:rack)
13
+ status, headers, response = @app.call(env)
14
+ [status, headers, response]
15
+ rescue
16
+ error = true
17
+ raise
18
+ ensure
19
+ Determinator::Tracking.finish!(
20
+ status: status,
21
+ error: !!error,
22
+ endpoint: extract_endpoint(env)
23
+ )
24
+ end
25
+
26
+ private
27
+
28
+ def extract_endpoint(env)
29
+ parts = if params = env['action_dispatch.request.path_parameters']
30
+ [env['REQUEST_METHOD'], [params[:controller], params[:action]].join('#')]
31
+ elsif env['sinatra.route']
32
+ [env['sinatra.route']]
33
+ else
34
+ [env['REQUEST_METHOD']]
35
+ end
36
+ Determinator::Tracking.collect_endpoint_info(parts)
37
+ rescue
38
+ env['PATH_INFO']
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,22 @@
1
+ module Determinator
2
+ module Tracking
3
+ class Request
4
+ attr_reader :start, :type, :endpoint, :time, :error, :attributes, :determinations, :context
5
+
6
+ def initialize(start:, type:, endpoint:, time:, error:, attributes:, determinations:, context: nil)
7
+ @start = start
8
+ @type = type
9
+ @time = time
10
+ @error = error
11
+ @attributes = attributes
12
+ @determinations = determinations
13
+ @endpoint = endpoint
14
+ @context = context
15
+ end
16
+
17
+ def error?
18
+ error
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,31 @@
1
+ require 'determinator/tracking'
2
+
3
+ module Determinator
4
+ module Tracking
5
+ module Sidekiq
6
+ class Middleware
7
+ # @param [Object] worker the worker instance
8
+ # @param [Hash] job the full job payload
9
+ # * @see https://github.com/mperham/sidekiq/wiki/Job-Format
10
+ # @param [String] queue the name of the queue the job was pulled from
11
+ # @yield the next middleware in the chain or worker `perform` method
12
+ # @return [Void]
13
+ def call(worker, job, queue)
14
+ begin
15
+ Determinator::Tracking.start!(:sidekiq)
16
+ yield
17
+ rescue => ex
18
+ error = true
19
+ raise
20
+ ensure
21
+ Determinator::Tracking.finish!(
22
+ endpoint: Determinator::Tracking.collect_endpoint_info(worker.class.name),
23
+ queue: queue,
24
+ error: !!error
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,48 @@
1
+ require 'determinator/tracking/determination'
2
+ require 'determinator/tracking/request'
3
+
4
+ module Determinator
5
+ module Tracking
6
+ class Tracker
7
+ attr_reader :type, :determinations
8
+
9
+ def initialize(type)
10
+ @determinations = Hash.new(0)
11
+ @type = type
12
+ @monotonic_start = now
13
+ @start = Time.now
14
+ end
15
+
16
+ def track(id, guid, feature, determination)
17
+ determinations[
18
+ Determinator::Tracking::Determination.new(
19
+ id: id,
20
+ guid: guid,
21
+ feature_id: feature.identifier,
22
+ determination: determination
23
+ )
24
+ ] += 1
25
+ end
26
+
27
+ def finish!(endpoint:, error:, **attributes)
28
+ request_time = now - @monotonic_start
29
+ Determinator::Tracking::Request.new(
30
+ start: @start,
31
+ type: type,
32
+ time: request_time,
33
+ endpoint: endpoint,
34
+ error: error,
35
+ attributes: attributes,
36
+ determinations: determinations,
37
+ context: Determinator::Tracking.context
38
+ )
39
+ end
40
+
41
+ private
42
+
43
+ def now
44
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,3 +1,3 @@
1
1
  module Determinator
2
- VERSION = '2.3.1'
2
+ VERSION = '2.5.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: determinator
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.1
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - JP Hastings-Spital
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-25 00:00:00.000000000 Z
11
+ date: 2020-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.13'
47
+ version: 2.1.4
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.13'
54
+ version: 2.1.4
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -136,7 +136,21 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
- description:
139
+ - !ruby/object:Gem::Dependency
140
+ name: sidekiq
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description:
140
154
  email:
141
155
  - jp@deliveroo.co.uk
142
156
  executables: []
@@ -196,6 +210,7 @@ files:
196
210
  - lib/determinator/control.rb
197
211
  - lib/determinator/error_response.rb
198
212
  - lib/determinator/feature.rb
213
+ - lib/determinator/fixed_determination.rb
199
214
  - lib/determinator/missing_response.rb
200
215
  - lib/determinator/retrieve/dynaconf.rb
201
216
  - lib/determinator/retrieve/file.rb
@@ -204,13 +219,20 @@ files:
204
219
  - lib/determinator/retrieve/null_retriever.rb
205
220
  - lib/determinator/serializers/json.rb
206
221
  - lib/determinator/target_group.rb
222
+ - lib/determinator/tracking.rb
223
+ - lib/determinator/tracking/context.rb
224
+ - lib/determinator/tracking/determination.rb
225
+ - lib/determinator/tracking/rack/middleware.rb
226
+ - lib/determinator/tracking/request.rb
227
+ - lib/determinator/tracking/sidekiq/middleware.rb
228
+ - lib/determinator/tracking/tracker.rb
207
229
  - lib/determinator/version.rb
208
230
  - lib/rspec/determinator.rb
209
231
  homepage: https://github.com/deliveroo/determinator
210
232
  licenses:
211
233
  - MIT
212
234
  metadata: {}
213
- post_install_message:
235
+ post_install_message:
214
236
  rdoc_options: []
215
237
  require_paths:
216
238
  - lib
@@ -225,9 +247,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
247
  - !ruby/object:Gem::Version
226
248
  version: '0'
227
249
  requirements: []
228
- rubyforge_project:
229
- rubygems_version: 2.7.9
230
- signing_key:
250
+ rubygems_version: 3.0.6
251
+ signing_key:
231
252
  specification_version: 4
232
253
  summary: Determine which experiments and features a specific actor should see.
233
254
  test_files: []