optimizely-sdk 3.4.0 → 3.8.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.
@@ -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/