optimizely-sdk 3.4.0 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2020, Optimizely and contributors
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'json'
20
+
21
+ module Optimizely
22
+ class OptimizelyUserContext
23
+ # Representation of an Optimizely User Context using which APIs are to be called.
24
+
25
+ attr_reader :user_id
26
+
27
+ def initialize(optimizely_client, user_id, user_attributes)
28
+ @attr_mutex = Mutex.new
29
+ @optimizely_client = optimizely_client
30
+ @user_id = user_id
31
+ @user_attributes = user_attributes.nil? ? {} : user_attributes.clone
32
+ end
33
+
34
+ def clone
35
+ OptimizelyUserContext.new(@optimizely_client, @user_id, user_attributes)
36
+ end
37
+
38
+ def user_attributes
39
+ @attr_mutex.synchronize { @user_attributes.clone }
40
+ end
41
+
42
+ # Set an attribute for a given key
43
+ #
44
+ # @param key - An attribute key
45
+ # @param value - An attribute value
46
+
47
+ def set_attribute(attribute_key, attribute_value)
48
+ @attr_mutex.synchronize { @user_attributes[attribute_key] = attribute_value }
49
+ end
50
+
51
+ # Returns a decision result (OptimizelyDecision) for a given flag key and a user context, which contains all data required to deliver the flag.
52
+ #
53
+ # If the SDK finds an error, it'll return a `decision` with nil for `variation_key`. The decision will include an error message in `reasons`
54
+ #
55
+ # @param key -A flag key for which a decision will be made
56
+ # @param options - A list of options for decision making.
57
+ #
58
+ # @return [OptimizelyDecision] A decision result
59
+
60
+ def decide(key, options = nil)
61
+ @optimizely_client&.decide(clone, key, options)
62
+ end
63
+
64
+ # Returns a hash of decision results (OptimizelyDecision) for multiple flag keys and a user context.
65
+ #
66
+ # If the SDK finds an error for a key, the response will include a decision for the key showing `reasons` for the error.
67
+ # The SDK will always return hash of decisions. When it can not process requests, it'll return an empty hash after logging the errors.
68
+ #
69
+ # @param keys - A list of flag keys for which the decisions will be made.
70
+ # @param options - A list of options for decision making.
71
+ #
72
+ # @return - Hash of decisions containing flag keys as hash keys and corresponding decisions as their values.
73
+
74
+ def decide_for_keys(keys, options = nil)
75
+ @optimizely_client&.decide_for_keys(clone, keys, options)
76
+ end
77
+
78
+ # Returns a hash of decision results (OptimizelyDecision) for all active flag keys.
79
+ #
80
+ # @param options - A list of options for decision making.
81
+ #
82
+ # @return - Hash of decisions containing flag keys as hash keys and corresponding decisions as their values.
83
+
84
+ def decide_all(options = nil)
85
+ @optimizely_client&.decide_all(clone, options)
86
+ end
87
+
88
+ # Track an event
89
+ #
90
+ # @param event_key - Event key representing the event which needs to be recorded.
91
+
92
+ def track_event(event_key, event_tags = nil)
93
+ @optimizely_client&.track(event_key, @user_id, user_attributes, event_tags)
94
+ end
95
+
96
+ def as_json
97
+ {
98
+ user_id: @user_id,
99
+ attributes: @user_attributes
100
+ }
101
+ end
102
+
103
+ def to_json(*args)
104
+ as_json.to_json(*args)
105
+ end
106
+ end
107
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2016-2019, Optimizely and contributors
3
+ # Copyright 2016-2020, Optimizely and contributors
4
4
  #
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
6
6
  # you may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@ module Optimizely
20
20
  # ProjectConfig is an interface capturing the experiment, variation and feature definitions.
21
21
  # The default implementation of ProjectConfig can be found in DatafileProjectConfig.
22
22
 
23
+ def datafile; end
24
+
23
25
  def account_id; end
24
26
 
25
27
  def attributes; end
@@ -44,6 +46,8 @@ module Optimizely
44
46
 
45
47
  def revision; end
46
48
 
49
+ def send_flag_decisions; end
50
+
47
51
  def rollouts; end
48
52
 
49
53
  def experiment_running?(experiment); end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2020, Optimizely and contributors
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require_relative 'exceptions'
20
+
21
+ module Optimizely
22
+ module SemanticVersion
23
+ # Semantic Version Operators
24
+ SEMVER_PRE_RELEASE = '-'
25
+ SEMVER_BUILD = '+'
26
+
27
+ module_function
28
+
29
+ def pre_release?(target)
30
+ # Method to check if the given version is a prerelease
31
+ #
32
+ # target - String representing semantic version
33
+ #
34
+ # Returns true if the given version is a prerelease
35
+ # false if it doesn't
36
+
37
+ raise unless target.is_a? String
38
+
39
+ prerelease_index = target.index(SEMVER_PRE_RELEASE)
40
+ build_index = target.index(SEMVER_BUILD)
41
+
42
+ return false if prerelease_index.nil?
43
+ return true if build_index.nil?
44
+
45
+ # when both operators are present prerelease should precede the build operator
46
+ prerelease_index < build_index
47
+ end
48
+
49
+ def build?(target)
50
+ # Method to check if the given version is a build
51
+ #
52
+ # target - String representing semantic version
53
+ #
54
+ # Returns true if the given version is a build
55
+ # false if it doesn't
56
+
57
+ raise unless target.is_a? String
58
+
59
+ prerelease_index = target.index(SEMVER_PRE_RELEASE)
60
+ build_index = target.index(SEMVER_BUILD)
61
+
62
+ return false if build_index.nil?
63
+ return true if prerelease_index.nil?
64
+
65
+ # when both operators are present build should precede the prerelease operator
66
+ build_index < prerelease_index
67
+ end
68
+
69
+ def split_semantic_version(target)
70
+ # Method to split the given version.
71
+ #
72
+ # target - String representing semantic version
73
+ #
74
+ # Returns List The array of version split into smaller parts i.e major, minor, patch etc,
75
+ # Exception if the given version is invalid.
76
+
77
+ target_prefix = target
78
+ target_suffix = ''
79
+ target_parts = []
80
+
81
+ raise InvalidSemanticVersion if target.include? ' '
82
+
83
+ if pre_release?(target)
84
+ target_parts = target.split(SEMVER_PRE_RELEASE, 2)
85
+ elsif build? target
86
+ target_parts = target.split(SEMVER_BUILD, 2)
87
+ end
88
+
89
+ unless target_parts.empty?
90
+ target_prefix = target_parts[0].to_s
91
+ target_suffix = target_parts[1..-1]
92
+ end
93
+
94
+ # expect a version string of the form x.y.z
95
+ dot_count = target_prefix.count('.')
96
+ raise InvalidSemanticVersion if dot_count > 2
97
+
98
+ target_version_parts = target_prefix.split('.')
99
+ raise InvalidSemanticVersion if target_version_parts.length != dot_count + 1
100
+
101
+ target_version_parts.each do |part|
102
+ raise InvalidSemanticVersion unless Helpers::Validator.string_numeric? part
103
+ end
104
+
105
+ target_version_parts.concat(target_suffix) if target_suffix.is_a?(Array)
106
+
107
+ target_version_parts
108
+ end
109
+
110
+ def compare_user_version_with_target_version(target_version, user_version)
111
+ # Compares target and user versions
112
+ #
113
+ # target_version - String representing target version
114
+ # user_version - String representing user version
115
+
116
+ # Returns boolean 0 if user version is equal to target version,
117
+ # 1 if user version is greater than target version,
118
+ # -1 if user version is less than target version.
119
+
120
+ raise InvalidAttributeType unless target_version.is_a? String
121
+ raise InvalidAttributeType unless user_version.is_a? String
122
+
123
+ is_target_version_prerelease = pre_release?(target_version)
124
+ is_user_version_prerelease = pre_release?(user_version)
125
+
126
+ target_version_parts = split_semantic_version(target_version)
127
+ user_version_parts = split_semantic_version(user_version)
128
+ user_version_parts_len = user_version_parts.length if user_version_parts
129
+
130
+ # Up to the precision of targetedVersion, expect version to match exactly.
131
+ target_version_parts.each_with_index do |_item, idx|
132
+ if user_version_parts_len <= idx
133
+ # even if they are equal at this point. if the target is a prerelease
134
+ # then user version must be greater than the pre release.
135
+ return 1 if is_target_version_prerelease
136
+
137
+ return -1
138
+
139
+ elsif !Helpers::Validator.string_numeric? user_version_parts[idx]
140
+ # compare strings
141
+ if user_version_parts[idx] < target_version_parts[idx]
142
+ return 1 if is_target_version_prerelease && !is_user_version_prerelease
143
+
144
+ return -1
145
+
146
+ elsif user_version_parts[idx] > target_version_parts[idx]
147
+ return -1 if is_user_version_prerelease && !is_target_version_prerelease
148
+
149
+ return 1
150
+ end
151
+
152
+ else
153
+ user_version_part = user_version_parts[idx].to_i
154
+ target_version_part = target_version_parts[idx].to_i
155
+
156
+ return 1 if user_version_part > target_version_part
157
+ return -1 if user_version_part < target_version_part
158
+ end
159
+ end
160
+
161
+ return -1 if is_user_version_prerelease && !is_target_version_prerelease
162
+
163
+ 0
164
+ end
165
+ end
166
+ end
@@ -17,5 +17,5 @@
17
17
  #
18
18
  module Optimizely
19
19
  CLIENT_ENGINE = 'ruby-sdk'
20
- VERSION = '3.4.0'
20
+ VERSION = '3.8.0'
21
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: optimizely-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.0
4
+ version: 3.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Optimizely
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-23 00:00:00.000000000 Z
11
+ date: 2021-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,20 +94,6 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: httparty
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '0.11'
104
- type: :runtime
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '0.11'
111
97
  - !ruby/object:Gem::Dependency
112
98
  name: json-schema
113
99
  requirement: !ruby/object:Gem::Requirement
@@ -149,11 +135,15 @@ files:
149
135
  - lib/optimizely/bucketer.rb
150
136
  - lib/optimizely/condition_tree_evaluator.rb
151
137
  - lib/optimizely/config/datafile_project_config.rb
138
+ - lib/optimizely/config/proxy_config.rb
152
139
  - lib/optimizely/config_manager/async_scheduler.rb
153
140
  - lib/optimizely/config_manager/http_project_config_manager.rb
154
141
  - lib/optimizely/config_manager/project_config_manager.rb
155
142
  - lib/optimizely/config_manager/static_project_config_manager.rb
156
143
  - lib/optimizely/custom_attribute_condition_evaluator.rb
144
+ - lib/optimizely/decide/optimizely_decide_option.rb
145
+ - lib/optimizely/decide/optimizely_decision.rb
146
+ - lib/optimizely/decide/optimizely_decision_message.rb
157
147
  - lib/optimizely/decision_service.rb
158
148
  - lib/optimizely/error_handler.rb
159
149
  - lib/optimizely/event/batch_event_processor.rb
@@ -178,14 +168,17 @@ files:
178
168
  - lib/optimizely/helpers/date_time_utils.rb
179
169
  - lib/optimizely/helpers/event_tag_utils.rb
180
170
  - lib/optimizely/helpers/group.rb
171
+ - lib/optimizely/helpers/http_utils.rb
181
172
  - lib/optimizely/helpers/validator.rb
182
173
  - lib/optimizely/helpers/variable_type.rb
183
174
  - lib/optimizely/logger.rb
184
175
  - lib/optimizely/notification_center.rb
185
176
  - lib/optimizely/optimizely_config.rb
186
177
  - lib/optimizely/optimizely_factory.rb
178
+ - lib/optimizely/optimizely_user_context.rb
187
179
  - lib/optimizely/params.rb
188
180
  - lib/optimizely/project_config.rb
181
+ - lib/optimizely/semantic_version.rb
189
182
  - lib/optimizely/user_profile_service.rb
190
183
  - lib/optimizely/version.rb
191
184
  homepage: https://www.optimizely.com/