-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add decide api #309
feat: add decide api #309
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good. Changes suggested.
optimizely/decision/decision.py
Outdated
# limitations under the License. | ||
|
||
|
||
class Decision(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change the name to "OptimizelyDecision"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 314
optimizely/decision/decide_option.py
Outdated
# limitations under the License. | ||
|
||
|
||
class DecideOption(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change the name to "OptimizelyDecideOption"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that is not consistent with the rest of the sdk
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 314
@@ -390,14 +391,15 @@ def get_experiment_in_group(self, project_config, group, bucketing_id): | |||
|
|||
return None | |||
|
|||
def get_variation_for_feature(self, project_config, feature, user_id, attributes=None): | |||
def get_variation_for_feature(self, project_config, feature, user_id, attributes=None, ignore_user_profile=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's interesting - I see that python-sdk already has "ignore_user_profile" option. We can keep the current structure to reuse it, but I'm concerned we may need to add options to support other options later.
optimizely/optimizely.py
Outdated
notification_center=None, | ||
event_processor=None, | ||
datafile_access_token=None, | ||
default_decisions=None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change this to "default_decide_options"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 314
optimizely/optimizely.py
Outdated
user_context = UserContext(self, user_id, attributes) | ||
return user_context | ||
|
||
def decide(self, user_context, key, decide_options=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make "decide", "decide_all" and "decide_for_keys" for internal access only (not public) if access can be controlled in python?
We want to let them use the APIs via UserContext always.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jaeopt Addressing this in my new PR. Python doesn't have real private methods or access control. The convention is to prefix a method with an underscore, if it's not meant to be called directly.
tests/test_user_context.py
Outdated
enums.NotificationTypes.DECISION, | ||
'feature', | ||
'test_user', | ||
{}, | ||
{ | ||
'feature_key': 'test_feature_in_experiment', | ||
'feature_enabled': True, | ||
'source': 'feature-test', | ||
'source_info': { | ||
'experiment': mock_experiment, | ||
'variation': mock_variation, | ||
}, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This notification type/contents should be changed.
tests/test_user_context.py
Outdated
'time.time', return_value=42 | ||
): | ||
context = opt_obj.create_user_context(user_id) | ||
decision = context.decide('test_feature_in_experiment', [DecideOption.DISABLE_DECISION_EVENT, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also need the same tests for default_decide_options.
tests/test_user_context.py
Outdated
) | ||
|
||
# Check that impression event is sent for rollout and send_flag_decisions = True | ||
self.assertEqual(1, mock_process.call_count) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we validate the event contents (at least metadata for flag decision)?
tests/test_user_context.py
Outdated
|
||
# Check that impression event is NOT sent for rollout and send_flag_decisions = True | ||
# with disable decision event decision option | ||
self.assertEqual(0, mock_process.call_count) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have one more test validating "IGNORE_USER_PROFILE" skips ups save() as well?
tests/test_user_context.py
Outdated
# with disable decision event decision option | ||
self.assertEqual(0, mock_process.call_count) | ||
|
||
def test_decide_options_reasons(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A test for "EXCLUDE_VARIABLES" missing?
* WIP * WIP * fix: Passes All FSC * fix: unit tests and cleanup * refact: rename decide classes * fix: merge default decide options in decide for keys * prefix decide methods with _ * fix: decide option import * mutex locks * Apply suggestions from code review Co-authored-by: Jae Kim <[email protected]> * tests: user context tests * tests: WIP * feat: reasons work * tests: refact * tests: Add unit tests * remove reasons from find_bucket * address comments * tests: decide * fix: import * tests: Add reasons tests Co-authored-by: Jae Kim <[email protected]>
@msohailhussain @jaeopt I have merged my PR. This PR should be good to go. |
Tests fail after merge. Can you take a look?
I guess this is the final one including all decide-api related changes. We
can just close #309, correct?
|
The unit tests are only failing on pypy and pypy3 due to a missing module. This error at times appear on travis builds. Not due to our change. Yes, this is the final one that should be merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Summary
Introducing a new primary interface for retrieving feature flag status, configuration and associated experiment decisions for users. The new OptimizelyUserContext class exposes the following APIs:
Test plan
Unit tests