tdeekens / flopflip

🎚Flip or flop features in your React application in real-time backed by flag provider of your choice 🚦
https://techblog.commercetools.com/embracing-real-time-feature-toggling-in-your-react-application-a5e6052716a9
MIT License
402 stars 40 forks source link

[Idea]: Decouple from LaunchDarkly (add more adapters) #40

Closed tdeekens closed 6 years ago

tdeekens commented 7 years ago

Currently flopflip is coupled to "only" LaunchDarkly as a provider for toggles this can change.

The library could potentially allow multiple providers for toggles and was actually built from the ground up to do so. Another packages/* to integrate with another provider and the configuration on of a consumer facing package should then pick any of the integrations behind the scenes. The API for an integration has a quite minimal surface area:

  1. Initialize (with allowing to defer it)
  2. Flush flags
  3. Flush updates

An integration is in charge of "doing" the targeting etc.

A simple idea is to integrate with an autoupdating/polling/streaming localstorage integration. Any app could, when receiving flags from it's backend, flush these to localstorage where the adapter/integration picks them up and they're automatically flushed to redux or the broadcasting variant.

tdeekens commented 6 years ago
  1. This would probably involve renaming ld-wrapper to launchdarkly-adapter
  2. This would include adding a localstorage-adapter
  3. This would include having to pass in an adapter to ConfigureFlopFlip manually

Possible examples to configure adapters

import launchdarklyAdapter from '@flopflip/launchdarkly-adapter';

<ConfigureFlopFlip adapter={launchdarklyAdapter} adapterArgs={{ clientSideId: '123' }}>
  <App />
<ConfigureFlopFlip>

//..

import localstorageAdapter from '@flopflip/localstorage-adapter';

<ConfigureFlopFlip adapter={localstorageAdapter}>
  <App />
<ConfigureFlopFlip>

or something like

import launchdarklyAdapter from '@flopflip/launchdarkly-adapter';

launchdarklyAdapter.configure({ ldClientSideId: '123' })

<ConfigureFlopFlip adapter={launchdarklyAdapter}>
  <App />
<ConfigureFlopFlip>

All adapters would have to satisfy an API which could be roughly something like

tdeekens commented 6 years ago

The localstorage adapter would

  1. Define a "constant" as a key to where flags are status data is persisted
  2. Expose the API above (same for the launchdarkly-adapter`
  3. Poll localstorage and "emit" changes though the onFlagsStateChange callback
tdeekens commented 6 years ago

Another adapter could be an url-adapter which reads the flag statuses from the url. Behind the scenes it could use something like https://github.com/ReactTraining/history

tdeekens commented 6 years ago

Another dapter could be an api-adapter which behind the scenes fetches flags from some service.

apiAdapter.configure({ url: 'http://my-great-service.com/flags', userKey: '123' })

It would then poll for changes taking the url http://my-great-service.com/flags/123. It compares the newly polled flags to the last and triggers the onFlagsStateChange callback to flush them into redux or the broadcasting mechanism.

tdeekens commented 6 years ago

Curious to what @dferber90 thinks if he finds time having a look πŸ˜… .

dferber90 commented 6 years ago

Adapters sound like a powerful concept.

Somehow seems like a perfect use-case for observable. But then again it would only raise more questions and we can achieve everything through functions already anyways. So I'd not use them.

After thinking about it a bit I'd prefer the version with adapterArgs as it provides a more natural to reconfigure the adapter in case information changes (like user logging out).

Maybe use a signature for the Adapter like this:

export default createAdapter = adapterArgs => (setStatusState, setFlagsState) => {
  setStatusState({ ready: true })
  setFlagsState({ FOO_FLAG: true })
}

Now either we only call the factory when adapterArgs' reference changes or we leave that to the adapter itself.

tdeekens commented 6 years ago

This will be part of #49. Thanks for all the feedback! Currently the launchdarkly-adapter has been ported while a memory-adapter has been created. The release will likely also contain a localstorage-adapter. Currently it feels like api-adapters are generally pretty bound to people's use cases, APIs and platforms. As a result I'd like to wait if someone actually needs on or if the implementation details settles.

dferber90 commented 6 years ago

πŸ‘β€οΈ