fix(core): Detect DB connection aquisition deadlocks (no-changelog) (#9485)

Co-authored-by: Danny Martini <danny@n8n.io>
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2024-05-22 14:53:23 +02:00
committed by GitHub
parent 2fa46b6faa
commit 3094f1b886
10 changed files with 53 additions and 66 deletions

View File

@@ -13,9 +13,9 @@ import { BaseCommand } from '../BaseCommand';
import type { ICredentialsEncrypted } from 'n8n-workflow';
import { ApplicationError, jsonParse } from 'n8n-workflow';
import { UM_FIX_INSTRUCTION } from '@/constants';
import { UserRepository } from '@db/repositories/user.repository';
import { ProjectRepository } from '@/databases/repositories/project.repository';
import type { Project } from '@/databases/entities/Project';
import { Project } from '@/databases/entities/Project';
import { User } from '@/databases/entities/User';
export class ImportCredentialsCommand extends BaseCommand {
static description = 'Import credentials';
@@ -75,13 +75,13 @@ export class ImportCredentialsCommand extends BaseCommand {
);
}
const project = await this.getProject(flags.userId, flags.projectId);
const credentials = await this.readCredentials(flags.input, flags.separate);
await Db.getConnection().transaction(async (transactionManager) => {
this.transactionManager = transactionManager;
const project = await this.getProject(flags.userId, flags.projectId);
const result = await this.checkRelations(credentials, flags.projectId, flags.userId);
if (!result.success) {
@@ -130,19 +130,6 @@ export class ImportCredentialsCommand extends BaseCommand {
}
}
private async getOwnerProject() {
const owner = await Container.get(UserRepository).findOneBy({ role: 'global:owner' });
if (!owner) {
throw new ApplicationError(`Failed to find owner. ${UM_FIX_INSTRUCTION}`);
}
const project = await Container.get(ProjectRepository).getPersonalProjectForUserOrFail(
owner.id,
);
return project;
}
private async checkRelations(
credentials: ICredentialsEncrypted[],
projectId?: string,
@@ -244,7 +231,7 @@ export class ImportCredentialsCommand extends BaseCommand {
});
if (sharedCredential && sharedCredential.project.type === 'personal') {
const user = await Container.get(UserRepository).findOneByOrFail({
const user = await this.transactionManager.findOneByOrFail(User, {
projectRelations: {
role: 'project:personalOwner',
projectId: sharedCredential.projectId,
@@ -263,13 +250,20 @@ export class ImportCredentialsCommand extends BaseCommand {
private async getProject(userId?: string, projectId?: string) {
if (projectId) {
return await Container.get(ProjectRepository).findOneByOrFail({ id: projectId });
return await this.transactionManager.findOneByOrFail(Project, { id: projectId });
}
if (userId) {
return await Container.get(ProjectRepository).getPersonalProjectForUserOrFail(userId);
if (!userId) {
const owner = await this.transactionManager.findOneBy(User, { role: 'global:owner' });
if (!owner) {
throw new ApplicationError(`Failed to find owner. ${UM_FIX_INSTRUCTION}`);
}
userId = owner.id;
}
return await this.getOwnerProject();
return await Container.get(ProjectRepository).getPersonalProjectForUserOrFail(
userId,
this.transactionManager,
);
}
}

View File

@@ -160,19 +160,6 @@ export class ImportWorkflowsCommand extends BaseCommand {
this.logger.info(`Successfully imported ${total} ${total === 1 ? 'workflow.' : 'workflows.'}`);
}
private async getOwnerProject() {
const owner = await Container.get(UserRepository).findOneBy({ role: 'global:owner' });
if (!owner) {
throw new ApplicationError(`Failed to find owner. ${UM_FIX_INSTRUCTION}`);
}
const project = await Container.get(ProjectRepository).getPersonalProjectForUserOrFail(
owner.id,
);
return project;
}
private async getWorkflowOwner(workflow: WorkflowEntity) {
const sharing = await Container.get(SharedWorkflowRepository).findOne({
where: { workflowId: workflow.id, role: 'workflow:owner' },
@@ -234,10 +221,14 @@ export class ImportWorkflowsCommand extends BaseCommand {
return await Container.get(ProjectRepository).findOneByOrFail({ id: projectId });
}
if (userId) {
return await Container.get(ProjectRepository).getPersonalProjectForUserOrFail(userId);
if (!userId) {
const owner = await Container.get(UserRepository).findOneBy({ role: 'global:owner' });
if (!owner) {
throw new ApplicationError(`Failed to find owner. ${UM_FIX_INSTRUCTION}`);
}
userId = owner.id;
}
return await this.getOwnerProject();
return await Container.get(ProjectRepository).getPersonalProjectForUserOrFail(userId);
}
}