Skip to content
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

Merged
merged 24 commits into from
Feb 1, 2021
Merged

feat: add decide api #309

merged 24 commits into from
Feb 1, 2021

Conversation

thomaszurkan-optimizely
Copy link
Contributor

@thomaszurkan-optimizely thomaszurkan-optimizely commented Nov 26, 2020

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:

- set_attribute
- decide
- decide_all
- decide_for_keys
- track_event

Test plan

Unit tests

@coveralls
Copy link

coveralls commented Nov 26, 2020

Coverage Status

Coverage decreased (-0.5%) to 95.883% when pulling 4f00cb5 on decideApi into be63510 on master.

@thomaszurkan-optimizely thomaszurkan-optimizely removed the wip Work in progress label Dec 3, 2020
Copy link
Contributor

@jaeopt jaeopt left a 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.

# limitations under the License.


class Decision(object):
Copy link
Contributor

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"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 314

# limitations under the License.


class DecideOption(object):
Copy link
Contributor

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"?

Copy link
Contributor Author

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

Copy link
Contributor

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):
Copy link
Contributor

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.

notification_center=None,
event_processor=None,
datafile_access_token=None,
default_decisions=None
Copy link
Contributor

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"?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 314

user_context = UserContext(self, user_id, attributes)
return user_context

def decide(self, user_context, key, decide_options=None):
Copy link
Contributor

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.

Copy link
Contributor

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.

Comment on lines 336 to 348
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,
},
},
Copy link
Contributor

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.

'time.time', return_value=42
):
context = opt_obj.create_user_context(user_id)
decision = context.decide('test_feature_in_experiment', [DecideOption.DISABLE_DECISION_EVENT,
Copy link
Contributor

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.

)

# Check that impression event is sent for rollout and send_flag_decisions = True
self.assertEqual(1, mock_process.call_count)
Copy link
Contributor

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)?


# 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)
Copy link
Contributor

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?

# with disable decision event decision option
self.assertEqual(0, mock_process.call_count)

def test_decide_options_reasons(self):
Copy link
Contributor

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]>
@oakbani
Copy link
Contributor

oakbani commented Feb 1, 2021

@msohailhussain @jaeopt I have merged my PR. This PR should be good to go.

@jaeopt
Copy link
Contributor

jaeopt commented Feb 1, 2021 via email

@oakbani
Copy link
Contributor

oakbani commented Feb 1, 2021

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.

Copy link
Contributor

@jaeopt jaeopt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jaeopt jaeopt merged commit 67b9f83 into master Feb 1, 2021
@jaeopt jaeopt deleted the decideApi branch February 1, 2021 22:17
@jaeopt jaeopt mentioned this pull request Feb 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants