-
Notifications
You must be signed in to change notification settings - Fork 752
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge organizations asynchronously (#1825)
- Loading branch information
1 parent
5e3bec5
commit bdca46b
Showing
14 changed files
with
277 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
backend/src/database/migrations/U1699357748__org-merge-status.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ALTER TABLE "organizationToMerge" DROP COLUMN status; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
DROP TABLE "mergeActions"; |
1 change: 1 addition & 0 deletions
1
backend/src/database/migrations/V1699357748__org-merge-status.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ALTER TABLE "organizationToMerge" ADD COLUMN status VARCHAR(16) NOT NULL DEFAULT 'ready'; |
13 changes: 13 additions & 0 deletions
13
backend/src/database/migrations/V1699459698__merge-actions.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
CREATE TABLE "mergeActions" ( | ||
id UUID PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(), | ||
"tenantId" UUID NOT NULL REFERENCES tenants (id) ON DELETE CASCADE, | ||
type VARCHAR(16) NOT NULL, -- org or member | ||
"primaryId" UUID NOT NULL, | ||
"secondaryId" UUID NOT NULL, | ||
"createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), | ||
"updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), | ||
"state" VARCHAR(16) NOT NULL, -- pending, in-progress, done | ||
UNIQUE ("tenantId", type, "primaryId", "secondaryId") | ||
); | ||
|
||
CREATE INDEX "mergeActions_main_idx" ON "mergeActions" (type, "primaryId", "secondaryId"); |
86 changes: 86 additions & 0 deletions
86
backend/src/database/repositories/mergeActionsRepository.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { QueryTypes } from 'sequelize' | ||
import { IRepositoryOptions } from './IRepositoryOptions' | ||
import SequelizeRepository from './sequelizeRepository' | ||
|
||
enum MergeActionType { | ||
ORG = 'org', | ||
MEMBER = 'member', | ||
} | ||
|
||
enum MergeActionState { | ||
PENDING = 'pending', | ||
IN_PROGRESS = 'in-progress', | ||
DONE = 'done', | ||
ERROR = 'error', | ||
} | ||
|
||
class MergeActionsRepository { | ||
static async add( | ||
type: MergeActionType, | ||
primaryId: string, | ||
secondaryId: string, | ||
options: IRepositoryOptions, | ||
) { | ||
const transaction = SequelizeRepository.getTransaction(options) | ||
const tenantId = options.currentTenant.id | ||
|
||
await options.database.sequelize.query( | ||
` | ||
INSERT INTO "mergeActions" ("tenantId", "type", "primaryId", "secondaryId", state) | ||
VALUES (:tenantId, :type, :primaryId, :secondaryId, :state) | ||
ON CONFLICT ("tenantId", "type", "primaryId", "secondaryId") | ||
DO UPDATE SET state = :state | ||
`, | ||
{ | ||
replacements: { | ||
tenantId, | ||
type, | ||
primaryId, | ||
secondaryId, | ||
state: MergeActionState.PENDING, | ||
}, | ||
type: QueryTypes.INSERT, | ||
transaction, | ||
}, | ||
) | ||
} | ||
|
||
static async setState( | ||
type: MergeActionType, | ||
primaryId: string, | ||
secondaryId: string, | ||
state: MergeActionState, | ||
options: IRepositoryOptions, | ||
) { | ||
const transaction = SequelizeRepository.getTransaction(options) | ||
const tenantId = options.currentTenant.id | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const [_, rowCount] = await options.database.sequelize.query( | ||
` | ||
UPDATE "mergeActions" | ||
SET state = :state | ||
WHERE "tenantId" = :tenantId | ||
AND type = :type | ||
AND "primaryId" = :primaryId | ||
AND "secondaryId" = :secondaryId | ||
AND state != :state | ||
`, | ||
{ | ||
replacements: { | ||
tenantId, | ||
type, | ||
primaryId, | ||
secondaryId, | ||
state, | ||
}, | ||
type: QueryTypes.UPDATE, | ||
transaction, | ||
}, | ||
) | ||
|
||
return rowCount > 0 | ||
} | ||
} | ||
|
||
export { MergeActionsRepository, MergeActionType, MergeActionState } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
backend/src/serverless/microservices/nodejs/org-merge/orgMergeWorker.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { getRedisClient, RedisPubSubEmitter } from '@crowd/redis' | ||
import { ApiWebsocketMessage } from '@crowd/types' | ||
import { REDIS_CONFIG } from '../../../../conf' | ||
import getUserContext from '../../../../database/utils/getUserContext' | ||
import OrganizationService from '../../../../services/organizationService' | ||
|
||
async function doNotifyFrontend({ log, success, tenantId, primaryOrgId, secondaryOrgId }) { | ||
const redis = await getRedisClient(REDIS_CONFIG, true) | ||
const apiPubSubEmitter = new RedisPubSubEmitter( | ||
'api-pubsub', | ||
redis, | ||
(err) => { | ||
log.error({ err }, 'Error in api-ws emitter!') | ||
}, | ||
log, | ||
) | ||
|
||
apiPubSubEmitter.emit( | ||
'user', | ||
new ApiWebsocketMessage( | ||
'org-merge', | ||
JSON.stringify({ | ||
success, | ||
tenantId, | ||
primaryOrgId, | ||
secondaryOrgId, | ||
}), | ||
undefined, | ||
tenantId, | ||
), | ||
) | ||
} | ||
|
||
async function orgMergeWorker( | ||
tenantId: string, | ||
primaryOrgId: string, | ||
secondaryOrgId: string, | ||
notifyFrontend: boolean, | ||
) { | ||
const userContext = await getUserContext(tenantId) | ||
|
||
const organizationService = new OrganizationService(userContext) | ||
|
||
let success = true | ||
try { | ||
await organizationService.mergeSync(primaryOrgId, secondaryOrgId) | ||
} catch (err) { | ||
userContext.log.error(err, 'Error merging orgs') | ||
success = false | ||
} | ||
|
||
if (notifyFrontend) { | ||
await doNotifyFrontend({ | ||
log: userContext.log, | ||
success, | ||
tenantId, | ||
primaryOrgId, | ||
secondaryOrgId, | ||
}) | ||
} | ||
} | ||
export { orgMergeWorker } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.