Skip to content

Commit

Permalink
feat: backfill current stage on startup (#7057)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwasniew authored May 15, 2024
1 parent 701c845 commit 6b59b30
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export class FakeFeatureLifecycleStore implements IFeatureLifecycleStore {
);
}

async backfill() {}

private async insertOne(
featureLifecycleStage: FeatureLifecycleStage,
): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export class FeatureLifecycleService extends EventEmitter {
}

listen() {
void this.checkEnabled(() => this.featureLifecycleStore.backfill());
this.eventStore.on(FEATURE_CREATED, async (event) => {
await this.checkEnabled(() =>
this.featureInitialized(event.featureName),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ export interface IFeatureLifecycleStore {
stageExists(stage: FeatureLifecycleStage): Promise<boolean>;
delete(feature: string): Promise<void>;
deleteStage(stage: FeatureLifecycleStage): Promise<void>;
backfill(): Promise<void>;
}
10 changes: 10 additions & 0 deletions src/lib/features/feature-lifecycle/feature-lifecycle-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ export class FeatureLifecycleStore implements IFeatureLifecycleStore {
this.db = db;
}

async backfill(): Promise<void> {
await this.db.raw(`
INSERT INTO feature_lifecycles (feature, stage, created_at)
SELECT features.name, 'initial', features.created_at
FROM features
LEFT JOIN feature_lifecycles ON features.name = feature_lifecycles.feature
WHERE feature_lifecycles.feature IS NULL
`);
}

async insert(
featureLifecycleStages: FeatureLifecycleStage[],
): Promise<void> {
Expand Down
20 changes: 20 additions & 0 deletions src/lib/features/feature-lifecycle/feature-lifecycle.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
FEATURE_CREATED,
FEATURE_REVIVED,
type IEventStore,
type IFeatureLifecycleStore,
type StageName,
} from '../../types';
import type EventEmitter from 'events';
Expand All @@ -24,6 +25,7 @@ import type { IFeatureLifecycleReadModel } from './feature-lifecycle-read-model-
let app: IUnleashTest;
let db: ITestDb;
let featureLifecycleService: FeatureLifecycleService;
let featureLifecycleStore: IFeatureLifecycleStore;
let eventStore: IEventStore;
let eventBus: EventEmitter;
let featureLifecycleReadModel: IFeatureLifecycleReadModel;
Expand All @@ -45,6 +47,7 @@ beforeAll(async () => {
eventBus = app.config.eventBus;
featureLifecycleService = app.services.featureLifecycleService;
featureLifecycleReadModel = new FeatureLifecycleReadModel(db.rawDatabase);
featureLifecycleStore = db.stores.featureLifecycleStore;

await app.request
.post(`/auth/demo/login`)
Expand Down Expand Up @@ -186,3 +189,20 @@ test('should be able to toggle between completed/uncompleted', async () => {

expect(body).toEqual([]);
});

test('should backfill initial stage when no stages', async () => {
await app.createFeature('my_feature_c');

await featureLifecycleStore.delete('my_feature_c');

const currentStage = await getCurrentStage('my_feature_c');
expect(currentStage).toBe(undefined);

await featureLifecycleStore.backfill();

const backfilledCurrentStage = await getCurrentStage('my_feature_c');
expect(backfilledCurrentStage).toEqual({
stage: 'initial',
enteredStageAt: expect.any(Date),
});
});

0 comments on commit 6b59b30

Please sign in to comment.