From 1cc22a61954b0e10e62241f91b39ff4324556430 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Sat, 5 Oct 2024 10:43:57 -0700 Subject: [PATCH 1/3] 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; From 128b1cf856c1005f1908f73351131887e8b9acb0 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Sat, 5 Oct 2024 11:01:30 -0700 Subject: [PATCH 2/3] fix: create separate triggers for insert/update --- .../utils/kmsKeySlugNameTransition.ts | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/backend/src/db/migrations/utils/kmsKeySlugNameTransition.ts b/backend/src/db/migrations/utils/kmsKeySlugNameTransition.ts index f7d295619..76cc9ea5f 100644 --- a/backend/src/db/migrations/utils/kmsKeySlugNameTransition.ts +++ b/backend/src/db/migrations/utils/kmsKeySlugNameTransition.ts @@ -7,29 +7,49 @@ import { TableName } from "@app/db/schemas"; // this is a postgres function to keep name in-sync with slug during transition period export const createKmsKeyNameSyncTrigger = async (knex: Knex) => { - // create function + // function to update name if slug is updated await knex.raw(` - CREATE OR REPLACE FUNCTION on_sync_kms_key_name() RETURNS TRIGGER AS $$ BEGIN NEW."name" = NEW."slug"; + CREATE OR REPLACE FUNCTION on_update_kms_key_slug() RETURNS TRIGGER AS $$ BEGIN NEW."name" = NEW."slug"; RETURN NEW; END; $$ LANGUAGE plpgsql; `); - // create trigger + // function to set name if kms key created with slug await knex.raw(` - CREATE TRIGGER "${TableName.KmsKey}_name_sync" - BEFORE INSERT OR UPDATE OF "slug" ON ${TableName.KmsKey} + CREATE OR REPLACE FUNCTION on_insert_kms_key() RETURNS TRIGGER AS $$ BEGIN NEW."name" = coalesce(NEW."name", NEW."slug"); + RETURN NEW; + END; + $$ LANGUAGE plpgsql; + `); + + // create trigger to update name if slug is updated + await knex.raw(` + CREATE TRIGGER "${TableName.KmsKey}_update_name" + BEFORE UPDATE OF "slug" ON ${TableName.KmsKey} FOR EACH ROW - EXECUTE PROCEDURE on_sync_kms_key_name(); + EXECUTE PROCEDURE on_update_kms_key_slug(); + `); + + // create trigger to set name if key created with slug + await knex.raw(` + CREATE TRIGGER "${TableName.KmsKey}_set_name" + BEFORE INSERT ON ${TableName.KmsKey} + FOR EACH ROW + EXECUTE PROCEDURE on_insert_kms_key(); `); }; export const dropKmsKeyNameSyncTrigger = async (knex: Knex) => { - // drop trigger - await knex.raw(`DROP TRIGGER IF EXISTS "${TableName.KmsKey}_name_sync" ON ${TableName.KmsKey}`); + // drop triggers + await knex.raw(`DROP TRIGGER IF EXISTS "${TableName.KmsKey}_update_name" ON ${TableName.KmsKey}`); + await knex.raw(`DROP TRIGGER IF EXISTS "${TableName.KmsKey}_set_name" ON ${TableName.KmsKey}`); - // drop function + // drop functions await knex.raw(` - DROP FUNCTION IF EXISTS on_sync_kms_key_name() CASCADE; + DROP FUNCTION IF EXISTS on_update_kms_key_slug() CASCADE; + `); + await knex.raw(` + DROP FUNCTION IF EXISTS on_insert_kms_key() CASCADE; `); }; From eef1f2b6ef42de5705f79c1e38a515f7e6613dd6 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Sat, 5 Oct 2024 18:05:50 -0700 Subject: [PATCH 3/3] remove trigger functions --- .../20241005170802_kms-keys-temp-slug-col.ts | 8 --- .../utils/kmsKeySlugNameTransition.ts | 55 ------------------- 2 files changed, 63 deletions(-) delete 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 index 1ddf843c0..45af3e4b8 100644 --- a/backend/src/db/migrations/20241005170802_kms-keys-temp-slug-col.ts +++ b/backend/src/db/migrations/20241005170802_kms-keys-temp-slug-col.ts @@ -1,9 +1,5 @@ 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 { @@ -17,8 +13,6 @@ export async function up(knex: Knex): Promise { table.string("slug", 32); }) .then(() => knex(TableName.KmsKey).update("slug", knex.ref("name"))); - - await createKmsKeyNameSyncTrigger(knex); } } } @@ -28,8 +22,6 @@ export async function down(knex: Knex): Promise { 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 deleted file mode 100644 index 76cc9ea5f..000000000 --- a/backend/src/db/migrations/utils/kmsKeySlugNameTransition.ts +++ /dev/null @@ -1,55 +0,0 @@ -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) => { - // function to update name if slug is updated - await knex.raw(` - CREATE OR REPLACE FUNCTION on_update_kms_key_slug() RETURNS TRIGGER AS $$ BEGIN NEW."name" = NEW."slug"; - RETURN NEW; - END; - $$ LANGUAGE plpgsql; - `); - - // function to set name if kms key created with slug - await knex.raw(` - CREATE OR REPLACE FUNCTION on_insert_kms_key() RETURNS TRIGGER AS $$ BEGIN NEW."name" = coalesce(NEW."name", NEW."slug"); - RETURN NEW; - END; - $$ LANGUAGE plpgsql; - `); - - // create trigger to update name if slug is updated - await knex.raw(` - CREATE TRIGGER "${TableName.KmsKey}_update_name" - BEFORE UPDATE OF "slug" ON ${TableName.KmsKey} - FOR EACH ROW - EXECUTE PROCEDURE on_update_kms_key_slug(); - `); - - // create trigger to set name if key created with slug - await knex.raw(` - CREATE TRIGGER "${TableName.KmsKey}_set_name" - BEFORE INSERT ON ${TableName.KmsKey} - FOR EACH ROW - EXECUTE PROCEDURE on_insert_kms_key(); - `); -}; - -export const dropKmsKeyNameSyncTrigger = async (knex: Knex) => { - // drop triggers - await knex.raw(`DROP TRIGGER IF EXISTS "${TableName.KmsKey}_update_name" ON ${TableName.KmsKey}`); - await knex.raw(`DROP TRIGGER IF EXISTS "${TableName.KmsKey}_set_name" ON ${TableName.KmsKey}`); - - // drop functions - await knex.raw(` - DROP FUNCTION IF EXISTS on_update_kms_key_slug() CASCADE; - `); - await knex.raw(` - DROP FUNCTION IF EXISTS on_insert_kms_key() CASCADE; - `); -};