Skip to content

Commit

Permalink
Merge pull request #54 from reddit/get_all_dynamic_configs
Browse files Browse the repository at this point in the history
Get all dynamic configs
  • Loading branch information
mrlevitas authored Jun 9, 2022
2 parents b430ad2 + 5372c67 commit 5f4fdd3
Show file tree
Hide file tree
Showing 4 changed files with 437 additions and 362 deletions.
96 changes: 78 additions & 18 deletions reddit_decider/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -656,33 +656,33 @@ def get_all_variants_without_expose(self) -> List[Dict[str, Union[str, int]]]:
logger.info(f"Encountered error in rust_decider.make_ctx(): {ctx_err}")
return []

all_choice_result = decider.choose_all(ctx)
all_decisions_result = decider.choose_all(ctx)

error = all_choice_result.err()
error = all_decisions_result.err()
if error:
logger.info(f"Encountered error in decider.choose_all(): {error}")
return []

all_choices = all_choice_result.decisions()
all_decisions = all_decisions_result.decisions()
parsed_choices = []

event_context_fields = self._decider_context.to_event_dict()

for exp_name, choice in all_choices.items():
choice_error = choice.err()
if choice_error:
for exp_name, decision in all_decisions.items():
decision_error = decision.err()
if decision_error:
logger.info(
f"Encountered error for experiment: {exp_name} in decider.choose_all(): {choice_error}"
f"Encountered error for experiment: {exp_name} in decider.choose_all(): {decision_error}"
)
continue

decision_dict = choice.decision_dict()
decision_dict = decision.decision_dict()

if decision_dict:
parsed_choices.append(self._format_decision(decision_dict))

# expose Holdout if the experiment is part of one
for event in choice.events():
for event in decision.events():
self._send_expose_if_holdout(event=event, exposure_fields=event_context_fields)

return parsed_choices
Expand Down Expand Up @@ -741,33 +741,33 @@ def get_all_variants_for_identifier_without_expose(
logger.info(f"Encountered error in rust_decider.make_ctx(): {ctx_err}")
return []

all_choice_result = decider.choose_all(ctx, identifier_type=identifier_type)
all_decisions_result = decider.choose_all(ctx=ctx, identifier_type=identifier_type)

error = all_choice_result.err()
error = all_decisions_result.err()
if error:
logger.info(f"Encountered error in decider.choose_all(): {error}")
return []

all_choices = all_choice_result.decisions()
all_decisions = all_decisions_result.decisions()
parsed_choices = []

event_context_fields = self._decider_context.to_event_dict()

for exp_name, choice in all_choices.items():
choice_error = choice.err()
if choice_error:
for exp_name, decision in all_decisions.items():
decision_error = decision.err()
if decision_error:
logger.info(
f"Encountered error for experiment: {exp_name} in decider.choose_all(): {choice_error}"
f"Encountered error for experiment: {exp_name} in decider.choose_all(): {decision_error}"
)
continue

decision_dict = choice.decision_dict()
decision_dict = decision.decision_dict()

if decision_dict:
parsed_choices.append(self._format_decision(decision_dict))

# expose Holdout if the experiment is part of one
for event in choice.events():
for event in decision.events():
self._send_expose_if_holdout(
event=event, exposure_fields=event_context_fields, overwrite_identifier=True
)
Expand Down Expand Up @@ -826,6 +826,66 @@ def get_map(self, feature_name: str, default: Optional[dict] = None) -> Optional
return default
return self._get_dynamic_config_value(feature_name, decider.get_map, default)

def get_all_dynamic_configs(self) -> List[Dict[str, Any]]:
"""Return a list of dynamic configuration dicts in this format:
[
{
"name": "example_dc",
"type": "float",
"value": 1.0,
},
...
]
where "type" field can be one of:
"boolean", "integer", "float", "string", or "map"
Dynamic Configurations that are malformed, fail parsing, or otherwirse
error for any reason are included in the response and have their respective default
values set:
"boolean" -> False
"integer" -> 0
"float" -> 0.0
"string" -> ""
"map" -> {}
:return: list of all active dynamic config dicts.
"""
decider = self._get_decider()
if not decider:
return []

ctx = self._get_ctx()
ctx_err = ctx.err()
if ctx_err is not None:
logger.info(f"Encountered error in rust_decider.make_ctx(): {ctx_err}")
return []

all_decisions_result = decider.get_all_values(ctx)

error = all_decisions_result.err()
if error:
logger.info(f"Encountered error in decider.choose_all(): {error}")
return []

all_decisions = all_decisions_result.decisions()
parsed_configs = []

for dc_name, decision in all_decisions.items():
decision_error = decision.err()
if decision_error:
logger.info(
f"Encountered error for dynamic config: {dc_name} in decider.get_all_values(): {decision_error}"
)
continue

value_dict = decision.value_dict()

if value_dict:
parsed_configs.append(value_dict)

return parsed_configs


class DeciderContextFactory(ContextFactory):
"""Decider client context factory.
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
alabaster==0.7.12
baseplate==2.0.0a1
black==21.4b2
reddit-decider==1.2.0
reddit-decider==1.2.2
flake8==3.9.1
mypy==0.790
pyramid==2.0 # required for `from baseplate.frameworks.pyramid import BaseplateRequest` which calls `import pyramid.events`
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
install_requires=[
"baseplate>=2.0.0a1,<3.0",
"reddit-edgecontext>=1.0.0a3,<2.0",
"reddit-decider>=1.2.0",
"reddit-decider>=1.2.2",
],
package_data={"reddit_experiments": ["py.typed"]},
zip_safe=True,
Expand Down
Loading

0 comments on commit 5f4fdd3

Please sign in to comment.