Skip to content

createInstance can throw: how to graceful fallback #134

@fabb

Description

@fabb

There are a few issues that make it impossible for the application to still work if optimizely fails to initialize:

  1. optimizely.createInstance from optimizely-sdk can return null
    https://github.com/optimizely/javascript-sdk/blob/v4.7.0/packages/optimizely-sdk/lib/index.browser.ts#L136
  2. createInstance in the react-sdk does not handle the null case and then just throws in the constructor when accessing this._client.onReady
    https://github.com/optimizely/react-sdk/blob/2.7.0/src/client.ts#L195-L201
  3. if we catch this thrown error in our application code, we cannot render OptimizelyProvider because it needs an OptimizelyReactSDKClient instance
    https://github.com/optimizely/react-sdk/blob/2.7.0/src/Provider.tsx#L27
  4. conditionally rendering the OptimizelyProvider is not an option because the optimizely hooks from react-sdk throw when there is no optimizely instance provided via the OptimizelyProvider
    https://github.com/optimizely/react-sdk/blob/2.7.0/src/hooks.ts#L332-L336
  5. the rules of hooks disallow to render hooks conditionally, so we cannot catch this issue on the application side

We currently see in production ~70.000 failed optimizely initializations / hour. All happening in Firefox, and we need to investigate more, but the main issue is that failing optimizely makes the application unusable, which is not a graceful fallback.

I have different ideas to solve this:

  1. react-sdk allows to render OptimizelyProvider with optimizely={null} and the optimizely hooks are modified to not throw anymore when no optimizely instance is available. Applications will need to catch the thrown error from the initial createInstance call and as a fallback use null. The hooks then fall back to the same values they would when optimizely is not yet ready.
  2. react-sdk does not throw in createInstance when optimizely is null and rather wraps all accesses to this._client with a null check.
  3. react-sdk provides a DummyReactClient that implements all the functions from ReactSDKClient with no functionality. Applications will need to catch the thrown error from the initial createInstance call and as a fallback use the DummyReactClient and provide it to OptimizelyProvider.

I would vote for option 1. because it still allows applications to detect when createInstance fails and allows for the maximum flexibility. Also it's backwards-compatible.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions