Skip to content

feat: implement decide API #634

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

Merged
merged 19 commits into from
Dec 9, 2020
Merged

feat: implement decide API #634

merged 19 commits into from
Dec 9, 2020

Conversation

yavorona
Copy link
Contributor

@yavorona yavorona commented Dec 8, 2020

Summary

  • Implemented decide API
  • Implemented Decide Reasons partially

Test

  • Manual testing + unit tests

Issues

@yavorona yavorona requested a review from a team as a code owner December 8, 2020 18:50
@yavorona yavorona removed their assignment Dec 8, 2020
@yavorona yavorona requested review from jaeopt and mjc1283 December 8, 2020 18:53
@coveralls
Copy link

coveralls commented Dec 8, 2020

Coverage Status

Coverage increased (+0.03%) to 96.764% when pulling 27c30a4 on pnguen/implement-decide-api into d658697 on master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.05%) to 96.761% when pulling 8d98a5d on pnguen/implement-decide-api into dfc1b7f on master.

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.

Looks good. A couple of changes and more tests suggested.

var expectedDecision = {
variationKey: null,
enabled: false,
variables: null,
Copy link
Contributor

Choose a reason for hiding this comment

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

return empty variables (instead of null) on error. Same for other tests.

});
});
});

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 api decide option ("EXCLUDE_VARIABLES") work together with defaultDecideOption ("DISABLE_DISPATCH_EVENT"), so we see both options are on.

assert.deepEqual(callArgs[0], expectedImpressionEvent);
});
});

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 add validation for decision flag notification?

return {
variationKey: null,
enabled: false,
variables: null,
Copy link
Contributor

Choose a reason for hiding this comment

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

Variable should be empty {} instead of null

});
}

decide(
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 sure "decide", "decideAll" and "decideForKey" API in optimizely not open to public?
They should access those APIs via OptimizelyUserContext always.

Copy link
Contributor

Choose a reason for hiding this comment

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

We can exclude them from the top-level type definitions.

@yavorona yavorona force-pushed the pnguen/implement-decide-api branch from 8d98a5d to ff8745b Compare December 8, 2020 22:57
clientEngine: 'node-sdk',
datafile: testData.getTestDecideProjectConfig(),
errorHandler: errorHandler,
eventDispatcher: eventDispatcher,
Copy link
Contributor

Choose a reason for hiding this comment

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

Using a real event dispatcher could cause event requests to be sent during test runs - we don't want that. We should pass in a fake event dispatcher.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

dispatchEvent of eventDispatcher is being stubbed in the outer beforeEach function, so I think we should be fine. @mjc1283 let me know if you think otherwise

clientEngine: 'node-sdk',
datafile: testData.getTestDecideProjectConfig(),
errorHandler: errorHandler,
eventDispatcher: eventDispatcher,
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment re: real event dispatcher.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please see my response above

}
assert.deepEqual(decision, expectedDecision);
sinon.assert.calledOnce(optlyInstance.eventDispatcher.dispatchEvent);
var expectedImpressionEvent = {
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO, asserting the whole structure of this object is a lot. We could do it one test, and then in the others, we could just check a few properties, or check that dispatchEvent was called.

// Filter out all provided default decide options that are not in OptimizelyDecideOptions[]
if (OptimizelyDecideOptions[option]) {
defaultDecideOptions[option] = true;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps we could log a warning here if we encounter an invalid value - @jaeopt WDYT?

* @return {[key: string]: boolean} Map of all provided decide options including default decide options
*/
private getAllDecideOptions(options: OptimizelyDecideOptions[]): { [key: string]: boolean } {
const allDecideOptions = {...this.defaultDecideOptions};
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks better! 👍

Comment on lines 1519 to 1520
const featureFlag = projectConfig.getFeatureFromKey(configObj, key, this.logger);
featureFlag?.variables.forEach(variable => {
Copy link
Contributor

Choose a reason for hiding this comment

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

We already have feature declared on 1474. Are these the same? Can we just use that one?

export interface OptimizelyDecision {
variationKey: string | null;
enabled: boolean;
variables: { [variableKey: string]: unknown } | null;
Copy link
Contributor

Choose a reason for hiding this comment

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

If following @jaeopt 's suggestion that this is an empty object when there is "no decision", we can remove | null;

@@ -117,6 +117,15 @@ export interface Rollout {
experiments: Experiment[];
}

//TODO: Move OptimizelyDecideOptions to @optimizely/optimizely-sdk/lib/utils/enums
Copy link
Contributor

Choose a reason for hiding this comment

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

Why move it there?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thinking it might be a good idea to expose it for clients use. LMKWYT @mjc1283

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point 👍

@yavorona yavorona removed their assignment Dec 9, 2020
} from '../shared_types';
import { OptimizelyDecision, newErrorDecision } from '../optimizely_decision/optimizely_decision';
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider: since there is only one file, we could name it optimizely_decision/index.ts, then it can be imported like import {...} from '../optimizely_decision';

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.

Decide notification format should be changed.

Comment on lines 1561 to 1565
type: DECISION_NOTIFICATION_TYPES.FLAG,
userId: userId,
attributes: attributes,
decisionInfo: featureInfo,
decisionEventDispatched: decisionEventDispatched,
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 data is different from the format defined in the TDD. Can you fix it?
Also can we have a test case to validate the notification contents for decide call?

@yavorona yavorona removed their assignment Dec 9, 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.

Remove "source" from notification. Other than that, all looks good.

featureKey: 'feature_2',
featureEnabled: true,
flagKey: 'feature_2',
enabled: true,
source: 'feature-test',
Copy link
Contributor

Choose a reason for hiding this comment

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

remove "source"

decisionInfo: {
flagKey: 'feature_2',
enabled: true,
source: 'feature-test',
Copy link
Contributor

Choose a reason for hiding this comment

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

remove "source"

@yavorona yavorona removed their assignment Dec 9, 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.

LGTM

@yavorona yavorona merged commit 132587e into master Dec 9, 2020
@yavorona yavorona deleted the pnguen/implement-decide-api branch December 9, 2020 22:28
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