-
Notifications
You must be signed in to change notification settings - Fork 2
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
refactor(core): move PrecomputedConfiguration into core #110
refactor(core): move PrecomputedConfiguration into core #110
Conversation
#[serde(rename_all = "camelCase")] | ||
pub struct PrecomputedAssignment { | ||
variation_type: VariationType, | ||
variation_value: ValueWire, |
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.
One diff here is that JSON assignment are now encoded as strings — following UFC flags config approach
#[serde(default, skip_serializing_if = "Option::is_none")] | ||
allocation_key: Option<Str>, | ||
#[serde(default, skip_serializing_if = "Option::is_none")] | ||
variation_key: Option<Str>, | ||
#[serde(default, skip_serializing_if = "Option::is_none")] | ||
extra_logging: Option<HashMap<String, String>>, |
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.
Decided to skip serializing these if do_log
is false for now. There is no reason for the client to need these except the logging purposes
/// `format` is always `AssignmentFormat::Precomputed`. | ||
format: AssignmentFormat, | ||
// Environment might be missing if configuration was absent during evaluation. | ||
environment: Option<Environment>, |
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.
There's no good default environment value, so decided to null
it instead of sending random string.
@@ -29,10 +31,38 @@ pub enum AssignmentValue { | |||
/// A boolean value. | |||
Boolean(bool), | |||
/// Arbitrary JSON value. | |||
Json(Arc<serde_json::Value>), | |||
Json { | |||
raw: 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.
Saving raw json value here. This will also allow us to return raw string in some SDKs if users want to use their own parser.
6bac46c
to
1041efc
Compare
pub format: AssignmentFormat, | ||
pub environment: Environment, | ||
pub flags: HashMap<String, Result<Assignment, EvaluationError>>, | ||
created_at: DateTime<Utc>, |
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.
Another change here is that all fields of PrecomputedConfiguration
are private to eppo_core
: edge server shouldn't need to tinker with them and clients would have their own parsers.
Basically, the only way to interact with PrecomputedConfiguration
is via serialize/deserialize.
This should allow us tweaking the type here without being afraid of breaking the edge server.
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.
Good idea! That's a nice way to signal where it should used, noted.
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 a single question on do_log
case
pub format: AssignmentFormat, | ||
pub environment: Environment, | ||
pub flags: HashMap<String, Result<Assignment, EvaluationError>>, | ||
created_at: DateTime<Utc>, |
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.
Good idea! That's a nice way to signal where it should used, noted.
None => PrecomputedAssignment { | ||
variation_type: assignment.value.variation_type(), | ||
variation_value: assignment.value.variation_value(), | ||
do_log: true, | ||
allocation_key: None, | ||
variation_key: None, | ||
extra_logging: 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.
good idea! thanks for figuring out how to handle these. If I'm understanding you correctly this will enable the getAssignment
to return a variation but it won't be logged.
Does it make sense here for do_log: false
?
None => PrecomputedAssignment { | |
variation_type: assignment.value.variation_type(), | |
variation_value: assignment.value.variation_value(), | |
do_log: true, | |
allocation_key: None, | |
variation_key: None, | |
extra_logging: None, | |
None => PrecomputedAssignment { | |
variation_type: assignment.value.variation_type(), | |
variation_value: assignment.value.variation_value(), | |
do_log: false, | |
allocation_key: None, | |
variation_key: None, | |
extra_logging: 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.
cc @sameerank looking at the implementation of (https://github.com/Eppo-exp/js-sdk-common/blob/main/src/client/eppo-precomputed-client.ts#L160-L185)
I see that this will return the variation value but I think logging is not desirable.
The background here is that during UFC compilation (an optimization step), we remove any allocations that are configured with do_log = false
and these evaluation to the default value. However for this API we need to return the variation value so that precompute client users can continue to use getAssignment
but without getting a log. Am I thinking about that correctly or is the code correct as-is?
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.
Yup, doLog
in the js client sdk is used to control if the assignment is logged, and if there's no allocation match, we shouldn't invoke the logger callback (if that's how the do_log
check is also getting used in eppo_core)
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.
Good catch — that was a typo. do_log
should be false
here. UPD: fixed
This is one of the reason why I love lifting data dependencies to type level. Instead of having a do_log
and a bunch of other fields that depend on it, the compiled configuration has a nullable event
field — no way to make the typo or for dependent fields to be missing
) -> PrecomputedConfiguration { | ||
let configuration = self.get_configuration(); | ||
get_precomputed_assignments( | ||
configuration.as_ref().map(AsRef::as_ref), | ||
&subject_key, | ||
&subject_attributes, | ||
early_exit, |
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.
👍 ok your philosophy is not to implement something without a use, I can understand that
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.
Wouldn't say it's my "philosophy" but in this case I'm pretty skeptical that we ever see a use case for early exit (given we spec'ed precomputed format and that it shouldn't early exit).
}, | ||
} | ||
|
||
impl PartialEq for AssignmentValue { |
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.
cool!
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.
haha, PartialEq
was auto-generated before but with adding raw
json strings, we can't compare on them (because serialization may differ), so I had to roll my own implementation — that's rather un-cool 😅
1041efc
to
f5f95a2
Compare
f4ecb00
into
lr/refactor-precomputed-assignments
#81) * refactor: split precomputed assignments between eppo-core and fastly-edge-assignments server. * reset * rename method * part of evaluator * EvaluationError * simplify no error * eppo_core 5.1.0 * compile and simplify * fix spec * refactor(core): move PrecomputedConfiguration into core (#110) * Revert "eppo_core 5.1.0" This reverts commit 9621c51. --------- Co-authored-by: Oleksii Shmalko <[email protected]>
@leoromanovsky this is opened to merge into #81