-
Notifications
You must be signed in to change notification settings - Fork 31
fix: bootstrapped client can do evaluation when not ready #1024
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,7 @@ import { | |
| Platform, | ||
| } from '@launchdarkly/js-client-sdk-common'; | ||
|
|
||
| import { readFlagsFromBootstrap } from './bootstrap'; | ||
| import { getHref } from './BrowserApi'; | ||
| import BrowserDataManager from './BrowserDataManager'; | ||
| import { BrowserIdentifyOptions as LDIdentifyOptions } from './BrowserIdentifyOptions'; | ||
|
|
@@ -32,6 +33,7 @@ import BrowserPlatform from './platform/BrowserPlatform'; | |
| class BrowserClientImpl extends LDClientImpl { | ||
| private readonly _goalManager?: GoalManager; | ||
| private readonly _plugins?: LDPlugin[]; | ||
| private _bootstrapAttempted = false; | ||
|
|
||
| constructor( | ||
| clientSideId: string, | ||
|
|
@@ -197,6 +199,12 @@ class BrowserClientImpl extends LDClientImpl { | |
| ); | ||
| } | ||
|
|
||
| /** | ||
| * @ignore | ||
| * NOTE: this identify is not doing anything as the `makeClient` function maps the | ||
| * identify function to identifyResults. We will need to consolidate this function | ||
| * in the js-client-sdk-common package. | ||
| */ | ||
| override async identify(context: LDContext, identifyOptions?: LDIdentifyOptions): Promise<void> { | ||
| return super.identify(context, identifyOptions); | ||
| } | ||
|
|
@@ -211,6 +219,21 @@ class BrowserClientImpl extends LDClientImpl { | |
| if (identifyOptions?.sheddable === undefined) { | ||
| identifyOptionsWithUpdatedDefaults.sheddable = true; | ||
| } | ||
|
|
||
| if (!this._bootstrapAttempted && identifyOptionsWithUpdatedDefaults.bootstrap) { | ||
| try { | ||
| const bootstrapData = readFlagsFromBootstrap( | ||
| this.logger, | ||
| identifyOptionsWithUpdatedDefaults.bootstrap, | ||
| ); | ||
| this.setBootstrap(context, bootstrapData); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Bootstrap uses unprocessed context causing potential key mismatchThe |
||
| } catch (e) { | ||
| this.logger.error('failed to bootstrap data'); | ||
| } finally { | ||
| this._bootstrapAttempted = true; | ||
| } | ||
| } | ||
|
|
||
| const res = await super.identifyResult(context, identifyOptionsWithUpdatedDefaults); | ||
| this._goalManager?.startTracking(); | ||
| return res; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,6 +43,7 @@ import createEventProcessor from './events/createEventProcessor'; | |
| import EventFactory from './events/EventFactory'; | ||
| import DefaultFlagManager, { FlagManager } from './flag-manager/FlagManager'; | ||
| import { FlagChangeType } from './flag-manager/FlagUpdater'; | ||
| import { ItemDescriptor } from './flag-manager/ItemDescriptor'; | ||
| import HookRunner from './HookRunner'; | ||
| import { getInspectorHook } from './inspection/getInspectorHook'; | ||
| import InspectorManager from './inspection/InspectorManager'; | ||
|
|
@@ -360,6 +361,19 @@ export default class LDClientImpl implements LDClient, LDClientIdentifyResult { | |
| return Promise.race([callSitePromise, timeoutPromise]); | ||
| } | ||
|
|
||
| /** | ||
| * Exposes the bootstrap functionality to the derived classes. This function is mainly used to help set | ||
| * flag values for bootstrapped clients before the initialization is complete. | ||
| * | ||
| * @param pristineContext The LDContext object to be identified. | ||
| * @param newFlags The new flags to set. | ||
| */ | ||
| protected setBootstrap(pristineContext: LDContext, newFlags: { [key: string]: ItemDescriptor }) { | ||
| this._uncheckedContext = pristineContext; | ||
| this._checkedContext = Context.fromLDContext(this._uncheckedContext); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume this will still get ultimately set by the normal code path, which would then handle any normal context processing? Do we need to be setting context information at all? I think in the previous SDK bootstrap would fail to send events before init complete, so this may be better for some cases.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think, if nothing else, we need to make sure that the bootstrap data actually gets set even if the context has anonymous contexts without keys.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea so it looks like the bootstrapping will fail when we use anonymous key... will look into this |
||
| this._flagManager.setBootstrap(this._checkedContext, newFlags); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Bootstrap fails silently for contexts without valid keysThe Additional Locations (1) |
||
|
|
||
| on(eventName: EventName, listener: Function): void { | ||
| this.emitter.on(eventName, listener); | ||
| } | ||
|
|
||
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.
I think we need to gate on only the very first identify if bootstrap is there.