mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
feat: Check production enabled live stage (#6952)
This commit is contained in:
parent
514a18bf93
commit
49e84d3a91
@ -9,8 +9,10 @@ import { FeatureLifecycleStore } from './feature-lifecycle-store';
|
|||||||
import EnvironmentStore from '../project-environments/environment-store';
|
import EnvironmentStore from '../project-environments/environment-store';
|
||||||
import EventService from '../events/event-service';
|
import EventService from '../events/event-service';
|
||||||
import FakeFeatureTagStore from '../../../test/fixtures/fake-feature-tag-store';
|
import FakeFeatureTagStore from '../../../test/fixtures/fake-feature-tag-store';
|
||||||
import { EventEmitter } from 'stream';
|
|
||||||
import FeatureTagStore from '../../db/feature-tag-store';
|
import FeatureTagStore from '../../db/feature-tag-store';
|
||||||
|
import { FeatureEnvironmentStore } from '../../db/feature-environment-store';
|
||||||
|
import FakeFeatureEnvironmentStore from '../../../test/fixtures/fake-feature-environment-store';
|
||||||
|
import EventEmitter from 'events';
|
||||||
|
|
||||||
export const createFeatureLifecycleService = (
|
export const createFeatureLifecycleService = (
|
||||||
db: Db,
|
db: Db,
|
||||||
@ -20,6 +22,11 @@ export const createFeatureLifecycleService = (
|
|||||||
const eventStore = new EventStore(db, getLogger);
|
const eventStore = new EventStore(db, getLogger);
|
||||||
const featureLifecycleStore = new FeatureLifecycleStore(db);
|
const featureLifecycleStore = new FeatureLifecycleStore(db);
|
||||||
const environmentStore = new EnvironmentStore(db, eventBus, getLogger);
|
const environmentStore = new EnvironmentStore(db, eventBus, getLogger);
|
||||||
|
const featureEnvironmentStore = new FeatureEnvironmentStore(
|
||||||
|
db,
|
||||||
|
eventBus,
|
||||||
|
getLogger,
|
||||||
|
);
|
||||||
const featureTagStore = new FeatureTagStore(
|
const featureTagStore = new FeatureTagStore(
|
||||||
db,
|
db,
|
||||||
config.eventBus,
|
config.eventBus,
|
||||||
@ -34,6 +41,7 @@ export const createFeatureLifecycleService = (
|
|||||||
eventStore,
|
eventStore,
|
||||||
featureLifecycleStore,
|
featureLifecycleStore,
|
||||||
environmentStore,
|
environmentStore,
|
||||||
|
featureEnvironmentStore,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventService,
|
eventService,
|
||||||
@ -53,6 +61,7 @@ export const createFakeFeatureLifecycleService = (config: IUnleashConfig) => {
|
|||||||
const eventStore = new FakeEventStore();
|
const eventStore = new FakeEventStore();
|
||||||
const featureLifecycleStore = new FakeFeatureLifecycleStore();
|
const featureLifecycleStore = new FakeFeatureLifecycleStore();
|
||||||
const environmentStore = new FakeEnvironmentStore();
|
const environmentStore = new FakeEnvironmentStore();
|
||||||
|
const featureEnvironmentStore = new FakeFeatureEnvironmentStore();
|
||||||
const eventService = new EventService(
|
const eventService = new EventService(
|
||||||
{ eventStore, featureTagStore: new FakeFeatureTagStore() },
|
{ eventStore, featureTagStore: new FakeFeatureTagStore() },
|
||||||
config,
|
config,
|
||||||
@ -62,6 +71,7 @@ export const createFakeFeatureLifecycleService = (config: IUnleashConfig) => {
|
|||||||
eventStore,
|
eventStore,
|
||||||
featureLifecycleStore,
|
featureLifecycleStore,
|
||||||
environmentStore,
|
environmentStore,
|
||||||
|
featureEnvironmentStore,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventService,
|
eventService,
|
||||||
@ -74,5 +84,6 @@ export const createFakeFeatureLifecycleService = (config: IUnleashConfig) => {
|
|||||||
featureLifecycleStore,
|
featureLifecycleStore,
|
||||||
eventStore,
|
eventStore,
|
||||||
environmentStore,
|
environmentStore,
|
||||||
|
featureEnvironmentStore,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -15,13 +15,22 @@ import noLoggerProvider from '../../../test/fixtures/no-logger';
|
|||||||
|
|
||||||
test('can insert and read lifecycle stages', async () => {
|
test('can insert and read lifecycle stages', async () => {
|
||||||
const eventBus = new EventEmitter();
|
const eventBus = new EventEmitter();
|
||||||
const { featureLifecycleService, eventStore, environmentStore } =
|
const {
|
||||||
createFakeFeatureLifecycleService({
|
featureLifecycleService,
|
||||||
flagResolver: { isEnabled: () => true },
|
eventStore,
|
||||||
eventBus,
|
environmentStore,
|
||||||
getLogger: noLoggerProvider,
|
featureEnvironmentStore,
|
||||||
} as unknown as IUnleashConfig);
|
} = createFakeFeatureLifecycleService({
|
||||||
|
flagResolver: { isEnabled: () => true },
|
||||||
|
eventBus,
|
||||||
|
getLogger: noLoggerProvider,
|
||||||
|
} as unknown as IUnleashConfig);
|
||||||
const featureName = 'testFeature';
|
const featureName = 'testFeature';
|
||||||
|
await featureEnvironmentStore.addEnvironmentToFeature(
|
||||||
|
featureName,
|
||||||
|
'my-prod-environment',
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
function emitMetricsEvent(environment: string) {
|
function emitMetricsEvent(environment: string) {
|
||||||
eventBus.emit(CLIENT_METRICS, {
|
eventBus.emit(CLIENT_METRICS, {
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
type IAuditUser,
|
type IAuditUser,
|
||||||
type IEnvironmentStore,
|
type IEnvironmentStore,
|
||||||
type IEventStore,
|
type IEventStore,
|
||||||
|
type IFeatureEnvironmentStore,
|
||||||
type IFlagResolver,
|
type IFlagResolver,
|
||||||
type IUnleashConfig,
|
type IUnleashConfig,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
@ -29,6 +30,8 @@ export class FeatureLifecycleService extends EventEmitter {
|
|||||||
|
|
||||||
private environmentStore: IEnvironmentStore;
|
private environmentStore: IEnvironmentStore;
|
||||||
|
|
||||||
|
private featureEnvironmentStore: IFeatureEnvironmentStore;
|
||||||
|
|
||||||
private flagResolver: IFlagResolver;
|
private flagResolver: IFlagResolver;
|
||||||
|
|
||||||
private eventBus: EventEmitter;
|
private eventBus: EventEmitter;
|
||||||
@ -42,10 +45,12 @@ export class FeatureLifecycleService extends EventEmitter {
|
|||||||
eventStore,
|
eventStore,
|
||||||
featureLifecycleStore,
|
featureLifecycleStore,
|
||||||
environmentStore,
|
environmentStore,
|
||||||
|
featureEnvironmentStore,
|
||||||
}: {
|
}: {
|
||||||
eventStore: IEventStore;
|
eventStore: IEventStore;
|
||||||
environmentStore: IEnvironmentStore;
|
environmentStore: IEnvironmentStore;
|
||||||
featureLifecycleStore: IFeatureLifecycleStore;
|
featureLifecycleStore: IFeatureLifecycleStore;
|
||||||
|
featureEnvironmentStore: IFeatureEnvironmentStore;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventService,
|
eventService,
|
||||||
@ -62,6 +67,7 @@ export class FeatureLifecycleService extends EventEmitter {
|
|||||||
this.eventStore = eventStore;
|
this.eventStore = eventStore;
|
||||||
this.featureLifecycleStore = featureLifecycleStore;
|
this.featureLifecycleStore = featureLifecycleStore;
|
||||||
this.environmentStore = environmentStore;
|
this.environmentStore = environmentStore;
|
||||||
|
this.featureEnvironmentStore = featureEnvironmentStore;
|
||||||
this.flagResolver = flagResolver;
|
this.flagResolver = flagResolver;
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
this.eventService = eventService;
|
this.eventService = eventService;
|
||||||
@ -140,7 +146,15 @@ export class FeatureLifecycleService extends EventEmitter {
|
|||||||
}
|
}
|
||||||
await this.stageReceivedMetrics(features, 'pre-live');
|
await this.stageReceivedMetrics(features, 'pre-live');
|
||||||
if (env.type === 'production') {
|
if (env.type === 'production') {
|
||||||
await this.stageReceivedMetrics(features, 'live');
|
const featureEnv =
|
||||||
|
await this.featureEnvironmentStore.getAllByFeatures(
|
||||||
|
features,
|
||||||
|
env.name,
|
||||||
|
);
|
||||||
|
const enabledFeatures = featureEnv
|
||||||
|
.filter((feature) => feature.enabled)
|
||||||
|
.map((feature) => feature.featureName);
|
||||||
|
await this.stageReceivedMetrics(enabledFeatures, 'live');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.warn(
|
this.logger.warn(
|
||||||
|
@ -98,6 +98,7 @@ const expectFeatureStage = async (featureName: string, stage: StageName) => {
|
|||||||
|
|
||||||
test('should return lifecycle stages', async () => {
|
test('should return lifecycle stages', async () => {
|
||||||
await app.createFeature('my_feature_a');
|
await app.createFeature('my_feature_a');
|
||||||
|
await app.enableFeature('my_feature_a', 'default');
|
||||||
eventStore.emit(FEATURE_CREATED, { featureName: 'my_feature_a' });
|
eventStore.emit(FEATURE_CREATED, { featureName: 'my_feature_a' });
|
||||||
await reachedStage('initial');
|
await reachedStage('initial');
|
||||||
await expectFeatureStage('my_feature_a', 'initial');
|
await expectFeatureStage('my_feature_a', 'initial');
|
||||||
|
@ -233,12 +233,16 @@ export default class FakeFeatureEnvironmentStore
|
|||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
getAllByFeatures(
|
async getAllByFeatures(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
features: string[],
|
features: string[],
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
environment?: string,
|
environment?: string,
|
||||||
): Promise<IFeatureEnvironment[]> {
|
): Promise<IFeatureEnvironment[]> {
|
||||||
throw new Error('Method not implemented.');
|
return this.featureEnvironments.filter(
|
||||||
|
(featureEnv) =>
|
||||||
|
(environment ? featureEnv.environment === environment : true) &&
|
||||||
|
features.includes(featureEnv.featureName),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user