1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-10 01:16:39 +02:00
unleash.unleash/src/lib/features/feature-lifecycle/feature-lifecycle-store.ts
Jaanus Sellin cd49ae2a26
feat: add project id to prometheus and feature flag (#7008)
Now we are also sending project id to prometheus, also querying from
database. This sets us up for grafana dashboard.
Also put the metrics behind flag, just incase it causes cpu/memory
issues.
2024-05-08 15:19:23 +03:00

103 lines
3.2 KiB
TypeScript

import type {
FeatureLifecycleStage,
IFeatureLifecycleStore,
FeatureLifecycleView,
FeatureLifecycleProjectItem,
} from './feature-lifecycle-store-type';
import type { Db } from '../../db/db';
import type { StageName } from '../../types';
type DBType = {
stage: StageName;
created_at: string;
};
type DBProjectType = DBType & {
feature: string;
project: string;
};
export class FeatureLifecycleStore implements IFeatureLifecycleStore {
private db: Db;
constructor(db: Db) {
this.db = db;
}
async insert(
featureLifecycleStages: FeatureLifecycleStage[],
): Promise<void> {
const joinedLifecycleStages = featureLifecycleStages
.map((stage) => `('${stage.feature}', '${stage.stage}')`)
.join(', ');
const query = this.db
.with(
'new_stages',
this.db.raw(`
SELECT v.feature, v.stage
FROM (VALUES ${joinedLifecycleStages}) AS v(feature, stage)
JOIN features ON features.name = v.feature
LEFT JOIN feature_lifecycles ON feature_lifecycles.feature = v.feature AND feature_lifecycles.stage = v.stage
WHERE feature_lifecycles.feature IS NULL AND feature_lifecycles.stage IS NULL
`),
)
.insert((query) => {
query.select('feature', 'stage').from('new_stages');
})
.into('feature_lifecycles')
.onConflict(['feature', 'stage'])
.ignore();
await query;
}
async get(feature: string): Promise<FeatureLifecycleView> {
const results = await this.db('feature_lifecycles')
.where({ feature })
.orderBy('created_at', 'asc');
return results.map(({ stage, created_at }: DBType) => ({
stage,
enteredStageAt: new Date(created_at),
}));
}
async getAll(): Promise<FeatureLifecycleProjectItem[]> {
const results = await this.db('feature_lifecycles as flc')
.select('flc.feature', 'flc.stage', 'flc.created_at', 'f.project')
.leftJoin('features f', 'f.name', 'flc.feature')
.orderBy('created_at', 'asc');
return results.map(
({ feature, stage, created_at, project }: DBProjectType) => ({
feature,
stage,
project,
enteredStageAt: new Date(created_at),
}),
);
}
async delete(feature: string): Promise<void> {
await this.db('feature_lifecycles').where({ feature }).del();
}
async deleteStage(stage: FeatureLifecycleStage): Promise<void> {
await this.db('feature_lifecycles')
.where({
stage: stage.stage,
feature: stage.feature,
})
.del();
}
async stageExists(stage: FeatureLifecycleStage): Promise<boolean> {
const result = await this.db.raw(
`SELECT EXISTS(SELECT 1 FROM feature_lifecycles WHERE stage = ? and feature = ?) AS present`,
[stage.stage, stage.feature],
);
const { present } = result.rows[0];
return present;
}
}