From c33935e5e11bd0811949b744d422f4c3ae7854f4 Mon Sep 17 00:00:00 2001 From: = Date: Wed, 22 Oct 2025 19:56:42 +0530 Subject: [PATCH] feat: resolved locking of membership table --- .../db/migrations/20251018061215_sub-org.ts | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/backend/src/db/migrations/20251018061215_sub-org.ts b/backend/src/db/migrations/20251018061215_sub-org.ts index 6378fa66a..95e96d8c8 100644 --- a/backend/src/db/migrations/20251018061215_sub-org.ts +++ b/backend/src/db/migrations/20251018061215_sub-org.ts @@ -3,6 +3,7 @@ import { Knex } from "knex"; import { dropConstraintIfExists } from "@app/db/migrations/utils/dropConstraintIfExists"; import { AccessScope, TableName } from "../schemas"; +import { chunkArray } from "@app/lib/fn"; export async function up(knex: Knex): Promise { const hasParentOrgId = await knex.schema.hasColumn(TableName.Organization, "parentOrgId"); @@ -29,19 +30,38 @@ export async function up(knex: Knex): Promise { t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE"); }); - await knex.raw( - ` - UPDATE ?? AS identity - SET "orgId" = membership."scopeOrgId" - FROM ?? AS membership - WHERE - membership."actorIdentityId" = identity."id" - AND membership."scope" = ? -`, - [TableName.Identity, TableName.Membership, AccessScope.Organization] - ); + const identityMemberships = await knex(TableName.Membership) + .where({ + scope: AccessScope.Organization + }) + .whereNotNull("actorIdentityId") + .select("actorIdentityId", "scopeOrgId"); - await knex.raw(`DELETE FROM ?? WHERE "orgId" IS NULL`, [TableName.Identity]); + const identityToOrgMapping: Record = {}; + identityMemberships.forEach((el) => { + if (el.actorIdentityId) { + identityToOrgMapping[el.actorIdentityId] = el.scopeOrgId; + } + }); + + const batchMemberships = chunkArray(identityMemberships, 500); + for await (const membership of batchMemberships) { + const identityIds = membership.map((el) => el.actorIdentityId).filter(Boolean) as string[]; + if (identityIds.length) { + const identities = await knex(TableName.Identity).whereIn("id", identityIds).select("*"); + await knex(TableName.Identity) + .insert( + identities.map((el) => ({ + ...el, + orgId: identityToOrgMapping[el.id] + })) + ) + .onConflict("id") + .merge(); + } + } + + await knex(TableName.Identity).whereNull("orgId").delete(); await knex.schema.alterTable(TableName.Identity, (t) => { t.uuid("orgId").notNullable().alter();