unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
102 lines • 4.07 kB
JavaScript
import EventEmitter from 'events';
import { mapFeaturesForClient, mapSegmentsForClient, } from '../playground/offline-unleash-client.js';
import { ALL_ENVS } from '../../util/constants.js';
import { UnleashEvents } from 'unleash-client';
import { UPDATE_REVISION } from '../feature-toggle/configuration-revision-service.js';
import { FUNCTION_TIME, PROXY_FEATURES_FOR_TOKEN_TIME, } from '../../metric-events.js';
import metricsHelper from '../../util/metrics-helper.js';
// TODO: remove after finished migration to global frontend api cache
export class ProxyRepository extends EventEmitter {
constructor(config, stores, services, token) {
super();
this.config = config;
this.logger = config.getLogger('proxy-repository.ts');
this.stores = stores;
this.services = services;
this.configurationRevisionService =
services.configurationRevisionService;
this.token = token;
this.onUpdateRevisionEvent = this.onUpdateRevisionEvent.bind(this);
this.interval = config.frontendApi.refreshIntervalInMs;
this.methodTimer = (functionName) => metricsHelper.wrapTimer(config.eventBus, FUNCTION_TIME, {
className: 'ProxyRepository',
functionName,
});
}
getTogglesWithSegmentData() {
// TODO: add real implementation
return [];
}
getSegment(id) {
return this.segments.find((segment) => segment.id === id);
}
getToggle(name) {
//@ts-expect-error (we must update the node SDK to allow undefined)
return this.features.find((feature) => feature.name === name);
}
getToggles() {
return this.features;
}
async start() {
this.running = true;
await this.dataPolling();
// Reload cached token data whenever something relevant has changed.
// For now, simply reload all the data on any EventStore event.
this.configurationRevisionService.on(UPDATE_REVISION, this.onUpdateRevisionEvent);
this.emit(UnleashEvents.Ready);
this.emit(UnleashEvents.Changed);
}
stop() {
this.configurationRevisionService.off(UPDATE_REVISION, this.onUpdateRevisionEvent);
this.running = false;
}
async dataPolling() {
this.timer = setTimeout(async () => {
if (!this.running) {
clearTimeout(this.timer);
this.timer = null;
this.logger.debug('Shutting down data polling for proxy repository');
return;
}
await this.dataPolling();
}, this.randomizeDelay(this.interval, this.interval * 2)).unref();
await this.loadDataForToken();
}
async loadDataForToken() {
try {
const stopTimer = this.methodTimer('loadDataForToken');
this.features = await this.featuresForToken();
this.segments = await this.segmentsForToken();
stopTimer();
}
catch (e) {
this.logger.error('Cannot load data for token', e);
}
}
randomizeDelay(floor, ceiling) {
return Math.floor(Math.random() * (ceiling - floor) + floor);
}
async onUpdateRevisionEvent() {
await this.loadDataForToken();
}
async featuresForToken() {
const start = Date.now();
const mappedFeatures = await mapFeaturesForClient(await this.services.featureToggleService.getClientFeatures({
project: this.token.projects,
environment: this.environmentNameForToken(),
}));
const duration = (Date.now() - start) / 1000;
this.config.eventBus.emit(PROXY_FEATURES_FOR_TOKEN_TIME, { duration });
return mappedFeatures;
}
async segmentsForToken() {
return mapSegmentsForClient(await this.stores.segmentReadModel.getAll());
}
environmentNameForToken() {
if (this.token.environment === ALL_ENVS) {
return 'default';
}
return this.token.environment;
}
}
//# sourceMappingURL=proxy-repository.js.map