Skip to content
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

API experiments system #296

Open
jasonkuhrt opened this issue Jan 16, 2020 · 1 comment
Open

API experiments system #296

jasonkuhrt opened this issue Jan 16, 2020 · 1 comment
Labels
scope/framework Related to something affecting the entire tool e.g. add JS support type/feat Add a new capability or enhance an existing one

Comments

@jasonkuhrt
Copy link
Member

What

  • A way to have unstable APIs in stable releases and have developers consuming this know the difference, with zero or almost zero additional cognitive load

Why

  • We want to explore topics like Server System #295 without going through long-lived PRs
  • We want to practice agile which means we need to incrementally ship
  • But incrementally shipping can go against great DX because results over time can be jagged, not seamless, inconsistent concepts or API style, etc.
  • The solution is a way to express the difference between experimental and non-experimental APIs

Sketches

  • We need a way for users to opt into experiments

     // app.ts
     import { app } from 'graphql-santa'
     
     app.settings.experiments.enable('foo', 'bar', 'qux')
     // or
     app.enableExperiment('foo')
     app.enableExperiment('foo')
     app.enableExperiment('qux')
     // or
     import { experiments } from 'graphql-santa'
     experiments.enable('...')
     // or
     // ...
  • There should be experiment support for worktime too, not just runtime... could defer this for another issue, e.g. make this one about "runtime experiments" and then another issue for "worktime experiments".

  • We need a way to mark functions as experimental:

     const experimentsLogger = logger.child('experiments')
    
     function experiment<F extends Function>(name: string, f: F): F {
     	return function (...args) {
     		if (project.settings.experiments[name].enabled) {
     			return f(...args)
     		} else {
     			if (project.settings.stage === 'production') {
     				throw new Error('...')
     			} else {
     				experimentLogger
     					.warning('not_enrolled', { experiment: name })
     					.pretty(`This is an experimental API. You are not allowed to use it until you explicitly opt-in. If you do not then your app will be force-exited in production. Please either stop using this API or opt-in. To opt-in add this to your settings:\n\n{ "experiments": { "${name}": true } }`)
     				f(...args)
     			}
     		}
     	}
     }
  • In the above:

    • somehow getting a reference to the user's project settings
    • warnings in dev, fatal in prod
    • nice logger integration
  • What about if experiments did not even show up in the API until being opted into?

    • dynamically set things to undefined
    • run typegen (this is the harder part)
    • is this simpler for the user?
    • By doing this we can add lots of experiments and not pollute the autocomplete for everyone
    • By doing this it makes trying experiments a little more annoying. Trying anything requires first opting in. With a warn-based approach user can try at will, deferring the configurations until go-to-prod time. In other words a warn approach is more gradual.
    • We could mitigate the criticism of autocomplete pollution by having a flag to enable experiments at all or not, if totally off, then typegen is used to not pollute autocomplete.
@jasonkuhrt jasonkuhrt added the type/feat Add a new capability or enhance an existing one label Jan 16, 2020
@Weakky
Copy link
Collaborator

Weakky commented Feb 4, 2020

I really, really like the approach where we mark experimental features and warn in dev. Again, I'd stay away from typegen as much as possible.

I also like your top-level experiments component. Makes me wonder whether experiments should live in the settings or live there. TBD.

@Weakky Weakky added the scope/framework Related to something affecting the entire tool e.g. add JS support label Jul 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
scope/framework Related to something affecting the entire tool e.g. add JS support type/feat Add a new capability or enhance an existing one
Projects
None yet
Development

No branches or pull requests

2 participants