-
Notifications
You must be signed in to change notification settings - Fork 7
Decider #6
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
Decider #6
Conversation
edit: package published to pypi as |
edit: and then running the new test via: |
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.
nice! You should probably have a BP.py expert like Andrew Boyle or similar look at this too.
"app_name": self._app_name, | ||
"build_number": self._build_number, | ||
"loid": self._loid, | ||
"cookie_created_timestamp": self._cookie_created_timestamp, |
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.
no event fields? That seems fine, if this is to be passed into decider
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.
user_event fields currently get passed under inputs
keyword in event_logger.log()
so I separated them out into get_user_event_fields()
function here which I combine with additional exposure_kwargs
passed into the fns ,in the commented out expose code, like so:
inputs = self._decider_context.get_user_event_fields()
inputs.update(exposure_kwargs or {})
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.
actually, I should combine self._decider_context.to_dict()
into inputs
as well to make some of the other fields available, such as bucketing_value, to the ExperimentsLogger, since it seems everything in input
will get dumped to the final v2 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.
removed get_user_event_fields()
since self._decider_context.to_dict()
contains the 3 fields that event_fields() contains
def test_none_returned_on_variant_call_with_bad_id(self): | ||
config = { | ||
"test": { | ||
"id": "1", |
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.
What will be the case to cause the id to be passed as str?
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.
just some general error handling, nothing particular--I took this test case from existing tests
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.
I see.
It is a non blocker but I think if ZK config is somehow passing str
id, maybe we should not silently return 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.
It's definitely a serious issue if that happens but I don't think we should raise an exception..at least it seems that the mentality of the experiments.py sdk is to log to warning instead of raising exceptions, which I do here (rust lib provides specific failure message to std out as well):
err: SerdeError(
Error("invalid type: string \"1\", expected u32", line: 1, column: 19),
)
WARNING reddit_decider:__init__.py:139 Rust decider did not initialize.
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.
maybe Rust decider did not initialize.
should be error
level log, instead of warning
though?
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.
I made the x = rust_decider.init()
return value have a way to access the error string via x.err()
(in this pr) so that we can control the error message in the sdk and log it to logger.error() without having rust lib print to std out and pollute logs.
user_id=user_event_fields.get("user_id"), | ||
logged_in=user_event_fields.get("logged_in"), |
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.
getting user_id
& logged_in
from ec.user.event_fields()
instead off of edge_context.user
directly to match current functionality.
Hi @pacejackson! |
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.
Looks great Roman! I noticed some functions don't have return types - do we wanna just always add return types moving forward? (e.g. to_dict())
* use rust decider crate tag * update readme & leave comment
…& expose() for now
…warning to error log for failed rust_decider.init()
f677b4d
to
510792f
Compare
… py version in makefile
Summary
This pr creates these classes:
DeciderContextFactory
(for baseplate setup)DeciderContext
(contains all fields used for bucketing, targeting, & exposure, e.g."user_id"
,"country_code"
, etc)Decider
(contains new API:get_variant()
)as well as the baseplate setup convenience function:
decider_client_from_config()
Todo:
DeciderClient
(convenience class for baseplate setup)get_variant_without_expose()
,expose()
onDecider
Expose logic has been implemented but commented out because Rust Decider lib needs to return a vector of events containing all of these fields:
for the exposure event (currently, the SDK is not
json.parse()
ing the experiment cfg json and deferring that to Rust Decider lib, so Rust has to return these fields).Testing
Unit tests for:
get_variant()
happy pathget_variant()
returnsNone
if the experiment's name is not in the configget_variant()
returnsNone
if the json config has an experiment'sid
as a str instead of an intget_variant()
returnsNone
if missing "experiment" key in json configAlso some basic unit test coverage of:
decider_client_from_config()
setupDeciderContextFactory.make_object_for_context()
correctly populatesDeciderContext
ivar inDecider
instanceMissing tests/todos:
DeciderClient
get_variant_without_expose()
expose()