From 2ba250fa411e00181c2042ddfbd77db3c220211e Mon Sep 17 00:00:00 2001 From: Jaanus Sellin Date: Tue, 30 Apr 2024 09:07:20 +0300 Subject: [PATCH] feat: do not insert into database stages that already exist (#6964) Previously when we had thousands of metrics coming in, we were trying to write them all to database and running into on conflict --- .../feature-lifecycle-store.ts | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/lib/features/feature-lifecycle/feature-lifecycle-store.ts b/src/lib/features/feature-lifecycle/feature-lifecycle-store.ts index 071dca5ddb..d34f22a617 100644 --- a/src/lib/features/feature-lifecycle/feature-lifecycle-store.ts +++ b/src/lib/features/feature-lifecycle/feature-lifecycle-store.ts @@ -22,29 +22,28 @@ export class FeatureLifecycleStore implements IFeatureLifecycleStore { async insert( featureLifecycleStages: FeatureLifecycleStage[], ): Promise { - const existingFeatures = await this.db('features') - .select('name') - .whereIn( - 'name', - featureLifecycleStages.map((stage) => stage.feature), - ); - const existingFeaturesSet = new Set( - existingFeatures.map((item) => item.name), - ); - const validStages = featureLifecycleStages.filter((stage) => - existingFeaturesSet.has(stage.feature), - ); + const joinedLifecycleStages = featureLifecycleStages + .map((stage) => `('${stage.feature}', '${stage.stage}')`) + .join(', '); - await this.db('feature_lifecycles') - .insert( - validStages.map((stage) => ({ - feature: stage.feature, - stage: stage.stage, - })), + 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 + `), ) - .returning('*') + .insert((query) => { + query.select('feature', 'stage').from('new_stages'); + }) + .into('feature_lifecycles') .onConflict(['feature', 'stage']) .ignore(); + await query; } async get(feature: string): Promise {