Skip to content

[Feature] Add ability to create single feature value subscription for all keys #207

@thedanchez

Description

@thedanchez

Is your feature request related to a problem? Please describe.

I am currently using FeatureHub Nodejs SDK for an enterprise project which is a simple client-server architecture. I have web SPA along with a web server that proxies requests. I am using that web-server to communicate with my org's FeatureHub instance to get updates.

The need I have is, I want to transmit flag value update events in real time to my client. This update should be across all flag keys defined as part of my app/project under my FH portfolio.

Describe the solution you'd like
I would like there to be a seamless way to get two things:

  • a snapshot of all defined features for an app (key data required: feature key and value)
  • subsequent updates to feature values over time

This perhaps all belongs within the ClientContext object? Or maybe the FeatureRepository ? Definitely can appreciate the complexity that can be present because depending on the rollout strategy for a feature, a certain user based on the client context configuration may not be authorized for a feature -- so perhaps it should belong with ClientContext? Haha 😂

Besides that question, I'm thinking it could expose something like the following:

// assume client context configured with all the meta-data information about the user

client.subscribeFeatures((features: readonly Feature[]) => {
  // when this listener/subscription is first established, I would expect an immediate response containing the current state of all feature flags belonging to the app (so that I have all of their keys/values)
// post the first "snapshot" call, subsequent executions of the listener should only occur due to feature updates so the features input could be a subset like only 1 feature value because someone updated a feature on the FeatureHub UI
})

Describe alternatives you've considered
Currently, I am doing the following to get an approximation to the above which I believe we can characterize as a very "unhealthy" solution 😂

class FeatureHub implements IFeatureFlagService {
  public readonly config: FeatureHubConfig;
  private readonly features: Map<string, FeatureHubFeature> = new Map();

  constructor({ url, apiKey, pollingInterval }: FeatureHubServiceConfig) {
    if (!url || !apiKey) {
      console.error("You must define the location of your FeatureHub Edge URL and your API Key");
      process.exit(-1);
    }

    FHLog.fhLog.trace = (...args: unknown[]) => {
      if (args[0] === "received features" || args[0] === "received feature") {
        const fhFeatures =
          args[0] === "received features"
            ? (args[1] as FeatureHubFeature[])
            : [args[1] as FeatureHubFeature];

        fhFeatures.forEach((fhFeature) => {
          this.features.set(fhFeature.key, fhFeature);
        });

        console.log([args[0]]);
        return;
      }

      console.log(args);
    };

    const fhConfig = new EdgeFeatureHubConfig(url, apiKey);

    if (pollingInterval) {
      fhConfig.edgeServiceProvider((repo, config) => {
        return new FeatureHubPollingClient(repo, config, pollingInterval);
      });
    }

    fhConfig.init();

    this.config = fhConfig;
  }
}

As you can see above, the FHLog trace logs two particular "events" that I am interested in.

This again is very brittle in my eyes but it first gives me "received features" which brings with it a list of all the feature objects currently defined within the app. I use that event response to get all the feature keys defined within the app and then I use the "received feature" event to update my cache of the local value I have stored due to processing all the features from the earlier snapshot.

I hope this is clear! Happy to expand if it is not!

Metadata

Metadata

Assignees

No one assigned

    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