-
Notifications
You must be signed in to change notification settings - Fork 83
feat(utils): Add PollingConfigCache and ClientCache #96
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
Conversation
2389a6b
to
6825f68
Compare
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.
Initial round of feedback. I need to spend more time looking at the cache implementations and maybe play around with them. Will get back to it later this week.
var Optimizely = require('./optimizely'); | ||
|
||
var MODULE_NAME = 'INDEX'; | ||
var { PollingConfigCache } = require('./utils/config_cache'); |
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.
Since this is supposed to be an overridable component, I think it should be in the plugins
directory as with the rest of the overridable components. Also, I was thinking we can even make this it's own package and later provide an entry point in here that allows users to not include that package (not that we can't do it without making it a separate package). Just drawing inspiration from other open source projects that split up in multiple packages like React
and Apollo
|
||
var MODULE_NAME = 'INDEX'; | ||
var { PollingConfigCache } = require('./utils/config_cache'); | ||
var { ClientCache } = require('./utils/client_cache'); | ||
|
||
/** | ||
* Entry point into the Optimizely Node testing SDK |
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.
This comment is no longer valid :)
return { | ||
body: await response.text(), | ||
headers: Array.from(response.headers.entries()).reduce((acc, [k, v]) => { | ||
acc[k] = v; |
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.
Please use proper variable names
] | ||
], | ||
"optionalDependencies": { | ||
"request": "^2.86.0", |
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.
@tylerbrandt later introduced this PR that removes this dependency because of vulnerabilities: #98 can we accomplish the same here using just http
and https
? Perhaps we can even have a promisified wrapper around them
} | ||
|
||
config = fns.assignIn({ | ||
clientEngine: enums.JAVASCRIPT_CLIENT_ENGINE, |
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.
This needs to vary by entrypoint because it lets the backend know whether it is a node or browser client.
* Fulfills ASAP in accord with the result of `__onGetAsync` or the given override. | ||
* Rejects on refresh error. | ||
*/ | ||
async getAsync(key, override) { |
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.
Document override
as an optional param. Also, can name it more explicitly, like refreshDirectiveOverride
.
/** | ||
* A ConfigCache that syncs by polling the CDN. | ||
* | ||
* Parametrized by which requester to use as a default, since Node.js and browser |
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.
Parameterized
/** | ||
* The function that PollingConfigCache should use by default to update a config. | ||
*/ | ||
async function browserRequester(url, headers) { |
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 move this into utils
or even plugins
(with the idea that we'll let you configure your own requester in a later version)? Let's try not to bloat the entry point file
this.__execRefresh(key); | ||
return this.get(key); | ||
|
||
case enums.refreshDirectives.YES_AWAIT: |
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.
We do need to handle the default case in case of user error and probably default to one of the above and log a warning about it.
* within this.configCache. _May_ involve losing per-instance state. In particular, | ||
* forcedVariations and notificationListeners are lost. TODO: Fix this. | ||
*/ | ||
async __refresh(configKey, { client: currentClient, config: currentConfig } = {}) { |
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.
please document params
This is stale, gonna close for now. |
Summary
PollingConfigCache
andClientCache
, both of which are subclasses of a [currently] private typeAsyncCache
createInstance
export tolib/optimizely/index.js
, in order to resolve a circular-import issue: sinceClientCache
refers to it, but the entry point modules in turn refer toClientCache
.How to read this: start with
AsyncCache
, then move on to the other types. It is a bit like the type exported by the popular async-cache package, but with some differences. This implementation:extend
ed, having methods overridden (likeseed
, whose semantics are quite different forClientCache
than they are forPollingConfigCache
).__execRefresh(key)
.process.nextTick
).This
AsyncCache
is totally generic, so could/should live in another package.Both the Node.js and browser builds (which reminds me, this PR must not be merged until babel transpilation is introduced) of
PollingConfigCache
have a functional default means of polling the CDN: request-promise-native and window.fetch, respectively. request-promise-native and its peer dependency "request" areoptionalDependencies
.Test plan
Currently some very basic unit tests. Some manual tests have validated basic
getAsync
use of both types, at-most-one-in-flight behavior, and support for tracking headers soPollingConfigCache
can get 304 responses from the CDN.