unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
97 lines • 3.94 kB
JavaScript
import EventEmitter from 'events';
import { mapFeatureForClient, mapSegmentsForClient, } from '../playground/offline-unleash-client.js';
import { ALL_ENVS, DEFAULT_ENV } from '../../util/constants.js';
import { UPDATE_REVISION } from '../feature-toggle/configuration-revision-service.js';
import metricsHelper from '../../util/metrics-helper.js';
import { FUNCTION_TIME } from '../../metric-events.js';
export class GlobalFrontendApiCache extends EventEmitter {
constructor(config, segmentReadModel, clientFeatureToggleReadModel, configurationRevisionService) {
super();
this.featuresByEnvironment = {};
this.segments = [];
this.status = 'starting';
this.config = config;
this.logger = config.getLogger('global-frontend-api-cache.ts');
this.clientFeatureToggleReadModel = clientFeatureToggleReadModel;
this.configurationRevisionService = configurationRevisionService;
this.segmentReadModel = segmentReadModel;
this.onUpdateRevisionEvent = this.onUpdateRevisionEvent.bind(this);
this.timer = (functionName) => metricsHelper.wrapTimer(config.eventBus, FUNCTION_TIME, {
className: 'GlobalFrontendApiCache',
functionName,
});
this.refreshData();
this.configurationRevisionService.on(UPDATE_REVISION, this.onUpdateRevisionEvent);
}
getSegment(id) {
return this.segments.find((segment) => segment.id === id);
}
getToggle(name, token) {
const features = this.getTogglesByEnvironment(this.environmentNameForToken(token));
return features[name];
}
getToggles(token) {
const features = this.getTogglesByEnvironment(this.environmentNameForToken(token));
return this.filterTogglesByProjects(features, token.projects);
}
filterTogglesByProjects(features, projects) {
if (projects.includes('*')) {
return Object.values(features);
}
return Object.values(features).filter((feature) => feature.project && projects.includes(feature.project));
}
getTogglesByEnvironment(environment) {
const features = this.featuresByEnvironment[environment];
if (features == null)
return {};
return features;
}
// TODO: fetch only relevant projects/environments based on tokens
async refreshData() {
try {
this.featuresByEnvironment = await this.getAllFeatures();
this.segments = await this.getAllSegments();
if (this.status === 'starting') {
this.status = 'ready';
this.emit('ready');
}
else if (this.status === 'ready' || this.status === 'updated') {
this.status = 'updated';
this.emit('updated');
}
}
catch (e) {
this.logger.error('Cannot load data for token', e);
}
}
async getAllFeatures() {
const features = await this.clientFeatureToggleReadModel.getAll();
return this.mapFeatures(features);
}
async getAllSegments() {
return mapSegmentsForClient(await this.segmentReadModel.getAll());
}
async onUpdateRevisionEvent() {
await this.refreshData();
}
environmentNameForToken(token) {
if (token.environment === ALL_ENVS) {
return DEFAULT_ENV;
}
return token.environment;
}
mapFeatures(features) {
const entries = Object.entries(features).map(([key, value]) => [
key,
Object.fromEntries(Object.entries(value).map(([innerKey, innerValue]) => [
innerKey,
mapFeatureForClient({
...innerValue,
stale: innerValue.stale || false,
}),
])),
]);
return Object.fromEntries(entries);
}
}
//# sourceMappingURL=global-frontend-api-cache.js.map