From 1cc22a61954b0e10e62241f91b39ff4324556430 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Sat, 5 Oct 2024 10:43:57 -0700 Subject: [PATCH] improvement: minizime kms key slug -> name transition impact --- .../20241005170802_kms-keys-temp-slug-col.ts | 38 +++++++++++++++++++ .../utils/kmsKeySlugNameTransition.ts | 35 +++++++++++++++++ backend/src/db/schemas/kms-keys.ts | 3 +- 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 backend/src/db/migrations/20241005170802_kms-keys-temp-slug-col.ts create mode 100644 backend/src/db/migrations/utils/kmsKeySlugNameTransition.ts diff --git a/backend/src/db/migrations/20241005170802_kms-keys-temp-slug-col.ts b/backend/src/db/migrations/20241005170802_kms-keys-temp-slug-col.ts new file mode 100644 index 000000000..1ddf843c0 --- /dev/null +++ b/backend/src/db/migrations/20241005170802_kms-keys-temp-slug-col.ts @@ -0,0 +1,38 @@ +import { Knex } from "knex"; + +import { + createKmsKeyNameSyncTrigger, + dropKmsKeyNameSyncTrigger +} from "@app/db/migrations/utils/kmsKeySlugNameTransition"; +import { TableName } from "@app/db/schemas"; + +export async function up(knex: Knex): Promise { + if (await knex.schema.hasTable(TableName.KmsKey)) { + const hasSlug = await knex.schema.hasColumn(TableName.KmsKey, "slug"); + + if (!hasSlug) { + // add slug back temporarily and set value equal to name + await knex.schema + .alterTable(TableName.KmsKey, (table) => { + table.string("slug", 32); + }) + .then(() => knex(TableName.KmsKey).update("slug", knex.ref("name"))); + + await createKmsKeyNameSyncTrigger(knex); + } + } +} + +export async function down(knex: Knex): Promise { + if (await knex.schema.hasTable(TableName.KmsKey)) { + const hasSlug = await knex.schema.hasColumn(TableName.KmsKey, "slug"); + + if (hasSlug) { + await dropKmsKeyNameSyncTrigger(knex); + + await knex.schema.alterTable(TableName.KmsKey, (table) => { + table.dropColumn("slug"); + }); + } + } +} diff --git a/backend/src/db/migrations/utils/kmsKeySlugNameTransition.ts b/backend/src/db/migrations/utils/kmsKeySlugNameTransition.ts new file mode 100644 index 000000000..f7d295619 --- /dev/null +++ b/backend/src/db/migrations/utils/kmsKeySlugNameTransition.ts @@ -0,0 +1,35 @@ +import { Knex } from "knex"; + +import { TableName } from "@app/db/schemas"; + +// These utils are meant to mitigate any delays between postgres update and application deployement for the KMS feature +// where slug col was migrated to name col + +// this is a postgres function to keep name in-sync with slug during transition period +export const createKmsKeyNameSyncTrigger = async (knex: Knex) => { + // create function + await knex.raw(` + CREATE OR REPLACE FUNCTION on_sync_kms_key_name() RETURNS TRIGGER AS $$ BEGIN NEW."name" = NEW."slug"; + RETURN NEW; + END; + $$ LANGUAGE plpgsql; + `); + + // create trigger + await knex.raw(` + CREATE TRIGGER "${TableName.KmsKey}_name_sync" + BEFORE INSERT OR UPDATE OF "slug" ON ${TableName.KmsKey} + FOR EACH ROW + EXECUTE PROCEDURE on_sync_kms_key_name(); + `); +}; + +export const dropKmsKeyNameSyncTrigger = async (knex: Knex) => { + // drop trigger + await knex.raw(`DROP TRIGGER IF EXISTS "${TableName.KmsKey}_name_sync" ON ${TableName.KmsKey}`); + + // drop function + await knex.raw(` + DROP FUNCTION IF EXISTS on_sync_kms_key_name() CASCADE; + `); +}; diff --git a/backend/src/db/schemas/kms-keys.ts b/backend/src/db/schemas/kms-keys.ts index b56fab7bf..dffaeec24 100644 --- a/backend/src/db/schemas/kms-keys.ts +++ b/backend/src/db/schemas/kms-keys.ts @@ -16,7 +16,8 @@ export const KmsKeysSchema = z.object({ name: z.string(), createdAt: z.date(), updatedAt: z.date(), - projectId: z.string().nullable().optional() + projectId: z.string().nullable().optional(), + slug: z.string().nullable().optional() }); export type TKmsKeys = z.infer;