DO NOT REVIEW - SEE https://github.com/optimizely/javascript-sdk/pull/288#216
DO NOT REVIEW - SEE https://github.com/optimizely/javascript-sdk/pull/288#216
Conversation
6c02325 to
2ae49e1
Compare
| function AudienceEvaluator(conditionEvaluators) { | ||
| this.typeToEvaluatorMap = Object.assign({ | ||
| 'custom_attribute': customAttributeConditionEvaluator | ||
| }, conditionEvaluators); |
There was a problem hiding this comment.
Do we just want allow for additional condition types beyond those supported by the javascript-sdk, or do we also want to allow customers to modify how the built-in condition types are evaluated?
If the former, I wonder if we can add some kind of namespacing (as in Optimizely Web audience integrations) to protect custom conditions types from conflicting with (existing and future) built-in condition types.
If the latter, I have serious reservations, since that could make it difficult for us to modify our own condition types without affecting existing customers.
There was a problem hiding this comment.
Yikes, we don't seem to catch errors when constructing the decision service. So if we apply any validation at this stage, or do anything that could throw an error, that error will bubble up into the customer's application.
Maybe we should do something about that! Though for the moment, I'm just pointing this out so that we remain careful not to throw.
There was a problem hiding this comment.
I like the approach of not allowing the built in evaluators to be overridden. If you need to do that, then you'll be able to write your own.
Good call on the error catching. Added an error message for that which is used in a try/catch now.
| function AudienceEvaluator(conditionEvaluators) { | ||
| this.typeToEvaluatorMap = Object.assign({ | ||
| 'custom_attribute': customAttributeConditionEvaluator | ||
| }, conditionEvaluators); |
There was a problem hiding this comment.
TODO: additional unit tests, eventually
|
Unit tests aren't passing in Travis, might wanna fix that and also merge |
mikeproeng37
left a comment
There was a problem hiding this comment.
I think the approach is fine so far. CCing @mjc1283 and @jordangarcia who have been doing work on extensibility and new components.
| return null; | ||
| } | ||
| try { | ||
| return evaluator.evaluate(condition, userAttributes, this.logger); |
There was a problem hiding this comment.
if the evaluator we get is not the custom_attribute, we should log a debug message to let the user know that. Might be helpful when trying to debug. Maybe we can even just log which evaluator we ended using (by key)
| this.configObj = options.configObj; | ||
| this.userProfileService = options.userProfileService || null; | ||
| this.logger = options.logger; | ||
| this.audienceEvaluator = new AudienceEvaluator(options.logger, options.__exploratoryConditionEvaluators); |
There was a problem hiding this comment.
This feels like we are polluting our factory method haha but I see no other easy way to integrate into the current setup.
There was a problem hiding this comment.
You mean the constructor?
Yea in the current setup, all this state must be threaded through (config, logger instance, etc...)
Would be nice to have a global registration system by instance ID so that this kinda global state can be easily accessed.
There was a problem hiding this comment.
This is totally fine, by adding configuration to the AudienceEvaluator we must capture that state, so making this an instantiatable class makes sense.
As far as global state, things like audience evaluators should not be considered as global state. If some sort of global registry existed you'd still have to know the instance ID here to resolve the audience evaluators (which would have to be threaded through).
However things like the logger and errorHandler should be global and having to thread them through here is not cool (this is changing soon in another PR)
jordangarcia
left a comment
There was a problem hiding this comment.
A few minor things about naming, but I think the structure of how the evaluator was made extensible looks good.
In terms of naming I've seen React use the prefix UNSTABLE_ in the public API and think that probably gets the point across more the "exploratory".
| configObj: optlyInstance.configObj, | ||
| userProfileService: userProfileServiceInstance, | ||
| logger: createdLogger, | ||
| __exploratoryConditionEvaluators: undefined |
There was a problem hiding this comment.
This is kind of a weird test assertion. It's probably fine, but I also think it makes sense for __exporatoryConditionEvaluators to be required in new Optimizely or Optimizely defaults this to {}
| this.configObj = options.configObj; | ||
| this.userProfileService = options.userProfileService || null; | ||
| this.logger = options.logger; | ||
| this.audienceEvaluator = new AudienceEvaluator(options.logger, options.__exploratoryConditionEvaluators); |
There was a problem hiding this comment.
This is totally fine, by adding configuration to the AudienceEvaluator we must capture that state, so making this an instantiatable class makes sense.
As far as global state, things like audience evaluators should not be considered as global state. If some sort of global registry existed you'd still have to know the instance ID here to resolve the audience evaluators (which would have to be threaded through).
However things like the logger and errorHandler should be global and having to thread them through here is not cool (this is changing soon in another PR)
| */ | ||
| function evaluate(condition, userAttributes, logger) { | ||
| if (condition.type !== CUSTOM_ATTRIBUTE_CONDITION_TYPE) { | ||
| logger.log(LOG_LEVEL.WARNING, sprintf(LOG_MESSAGES.UNKNOWN_CONDITION_TYPE, MODULE_NAME, JSON.stringify(condition))); |
There was a problem hiding this comment.
@jamesopti I see this log message now in AudienceEvaluator.prototype.evaluateConditionWithUserAttributes - what is the purpose of this evaluate function, now?
|
DO NOT REVIEW - SEE #288 |
|
Obsolete |
Summary
This PR adds the ability for an SDK consumer to pass their own set of condition evaluators when creating an optimizely instance.
The core motivator for this is to be able to evaluate WEB audience conditions using the Javascript SDK as part of the EDGE project (go/edge).
Future fullstack use cases for this functionality might include audience condition plugins, where the customer would define their own match types and provide their own matchers.
Test plan
Unit tests would be pretty straightforward to add for this
Issues