Stop switching to a different datasource per workspace (#3425)

* Stop switching to a different datasource per workspace

* Add console

* Remove call to metadata
This commit is contained in:
Charles Bochet
2024-01-14 00:21:21 +01:00
committed by GitHub
parent 95326b2828
commit 8893cbc05d
25 changed files with 83 additions and 32 deletions

View File

@ -37,27 +37,35 @@ export class TypeORMService implements OnModuleInit, OnModuleDestroy {
public async connectToDataSource(
dataSource: DataSourceEntity,
): Promise<DataSource | undefined> {
// Wait for a bit before trying again if another initialization is in progress
while (this.isDatasourceInitializing.get(dataSource.id)) {
await new Promise((resolve) => setTimeout(resolve, 10));
const isMultiDatasourceEnabled = false;
console.log('Data sources number', this.dataSources.size);
if (isMultiDatasourceEnabled) {
// Wait for a bit before trying again if another initialization is in progress
while (this.isDatasourceInitializing.get(dataSource.id)) {
await new Promise((resolve) => setTimeout(resolve, 10));
}
if (this.dataSources.has(dataSource.id)) {
return this.dataSources.get(dataSource.id);
}
this.isDatasourceInitializing.set(dataSource.id, true);
try {
const dataSourceInstance =
await this.createAndInitializeDataSource(dataSource);
this.dataSources.set(dataSource.id, dataSourceInstance);
return dataSourceInstance;
} finally {
this.isDatasourceInitializing.delete(dataSource.id);
}
}
if (this.dataSources.has(dataSource.id)) {
return this.dataSources.get(dataSource.id);
}
this.isDatasourceInitializing.set(dataSource.id, true);
try {
const dataSourceInstance =
await this.createAndInitializeDataSource(dataSource);
this.dataSources.set(dataSource.id, dataSourceInstance);
return dataSourceInstance;
} finally {
this.isDatasourceInitializing.delete(dataSource.id);
}
return this.mainDataSource;
}
private async createAndInitializeDataSource(

View File

@ -298,6 +298,7 @@ export class WorkspaceMigrationRunnerService {
columnNames: [migrationColumn.columnName],
referencedColumnNames: [migrationColumn.referencedTableColumnName],
referencedTableName: migrationColumn.referencedTableName,
referencedSchema: schemaName,
onDelete: 'CASCADE',
}),
);

View File

@ -27,6 +27,7 @@ export class CreateManyQueryFactory {
const fieldsString = await this.fieldsStringFactory.create(
options.info,
options.fieldMetadataCollection,
options.objectMetadataCollection,
);
const computedArgs = this.argsAliasFactory.create(
args,

View File

@ -18,6 +18,7 @@ export class DeleteManyQueryFactory {
const fieldsString = await this.fieldsStringFactory.create(
options.info,
options.fieldMetadataCollection,
options.objectMetadataCollection,
);
return `

View File

@ -18,6 +18,7 @@ export class DeleteOneQueryFactory {
const fieldsString = await this.fieldsStringFactory.create(
options.info,
options.fieldMetadataCollection,
options.objectMetadataCollection,
);
return `

View File

@ -5,6 +5,7 @@ import graphqlFields from 'graphql-fields';
import isEmpty from 'lodash.isempty';
import { FieldMetadataInterface } from 'src/metadata/field-metadata/interfaces/field-metadata.interface';
import { ObjectMetadataInterface } from 'src/metadata/field-metadata/interfaces/object-metadata.interface';
import { isRelationFieldMetadataType } from 'src/workspace/utils/is-relation-field-metadata-type.util';
@ -23,6 +24,7 @@ export class FieldsStringFactory {
create(
info: GraphQLResolveInfo,
fieldMetadataCollection: FieldMetadataInterface[],
objectMetadataCollection: ObjectMetadataInterface[],
): Promise<string> {
const selectedFields: Record<string, any> = graphqlFields(info);
@ -30,6 +32,7 @@ export class FieldsStringFactory {
info,
selectedFields,
fieldMetadataCollection,
objectMetadataCollection,
);
}
@ -37,6 +40,7 @@ export class FieldsStringFactory {
info: GraphQLResolveInfo,
selectedFields: Record<string, any>,
fieldMetadataCollection: FieldMetadataInterface[],
objectMetadataCollection: ObjectMetadataInterface[],
accumulator = '',
): Promise<string> {
const fieldMetadataMap = new Map(
@ -58,6 +62,7 @@ export class FieldsStringFactory {
fieldKey,
fieldValue,
fieldMetadata,
objectMetadataCollection,
info,
);
@ -84,6 +89,7 @@ export class FieldsStringFactory {
info,
fieldValue,
fieldMetadataCollection,
objectMetadataCollection,
accumulator,
);
accumulator += `}\n`;

View File

@ -29,6 +29,7 @@ export class FindManyQueryFactory {
const fieldsString = await this.fieldsStringFactory.create(
options.info,
options.fieldMetadataCollection,
options.objectMetadataCollection,
);
const argsString = this.argsStringFactory.create(
args,

View File

@ -23,6 +23,7 @@ export class FindOneQueryFactory {
const fieldsString = await this.fieldsStringFactory.create(
options.info,
options.fieldMetadataCollection,
options.objectMetadataCollection,
);
const argsString = this.argsStringFactory.create(
args,

View File

@ -3,6 +3,7 @@ import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common';
import { GraphQLResolveInfo } from 'graphql';
import { FieldMetadataInterface } from 'src/metadata/field-metadata/interfaces/field-metadata.interface';
import { ObjectMetadataInterface } from 'src/metadata/field-metadata/interfaces/object-metadata.interface';
import { isRelationFieldMetadataType } from 'src/workspace/utils/is-relation-field-metadata-type.util';
import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-metadata.entity';
@ -31,19 +32,27 @@ export class RelationFieldAliasFactory {
fieldKey: string,
fieldValue: any,
fieldMetadata: FieldMetadataInterface,
objectMetadataCollection: ObjectMetadataInterface[],
info: GraphQLResolveInfo,
): Promise<string> {
if (!isRelationFieldMetadataType(fieldMetadata.type)) {
throw new Error(`Field ${fieldMetadata.name} is not a relation field`);
}
return this.createRelationAlias(fieldKey, fieldValue, fieldMetadata, info);
return this.createRelationAlias(
fieldKey,
fieldValue,
fieldMetadata,
objectMetadataCollection,
info,
);
}
private async createRelationAlias(
fieldKey: string,
fieldValue: any,
fieldMetadata: FieldMetadataInterface,
objectMetadataCollection: ObjectMetadataInterface[],
info: GraphQLResolveInfo,
): Promise<string> {
const relationMetadata =
@ -67,18 +76,13 @@ export class RelationFieldAliasFactory {
);
// Retrieve the referenced object metadata based on the relation direction
// Mandatory to handle n+n relations
const referencedObjectMetadata =
await this.objectMetadataService.findOneWithinWorkspace(
fieldMetadata.workspaceId,
{
where: {
id:
relationDirection == RelationDirection.TO
? relationMetadata.fromObjectMetadataId
: relationMetadata.toObjectMetadataId,
},
},
);
const referencedObjectMetadata = objectMetadataCollection.find(
(objectMetadata) =>
objectMetadata.id ===
(relationDirection == RelationDirection.TO
? relationMetadata.fromObjectMetadataId
: relationMetadata.toObjectMetadataId),
);
if (!referencedObjectMetadata) {
throw new Error(
@ -101,6 +105,7 @@ export class RelationFieldAliasFactory {
info,
fieldValue,
referencedObjectMetadata.fields ?? [],
objectMetadataCollection,
);
return `
@ -129,6 +134,7 @@ export class RelationFieldAliasFactory {
info,
fieldValue,
referencedObjectMetadata.fields ?? [],
objectMetadataCollection,
);
// Otherwise it means it's a relation destination is of kind ONE

View File

@ -28,6 +28,7 @@ export class UpdateManyQueryFactory {
const fieldsString = await this.fieldsStringFactory.create(
options.info,
options.fieldMetadataCollection,
options.objectMetadataCollection,
);
const computedArgs = this.argsAliasFactory.create(

View File

@ -25,6 +25,7 @@ export class UpdateOneQueryFactory {
const fieldsString = await this.fieldsStringFactory.create(
options.info,
options.fieldMetadataCollection,
options.objectMetadataCollection,
);
const computedArgs = this.argsAliasFactory.create(
args,

View File

@ -1,9 +1,11 @@
import { GraphQLResolveInfo } from 'graphql';
import { FieldMetadataInterface } from 'src/metadata/field-metadata/interfaces/field-metadata.interface';
import { ObjectMetadataInterface } from 'src/metadata/field-metadata/interfaces/object-metadata.interface';
export interface WorkspaceQueryBuilderOptions {
targetTableName: string;
info: GraphQLResolveInfo;
fieldMetadataCollection: FieldMetadataInterface[];
objectMetadataCollection: ObjectMetadataInterface[];
}

View File

@ -1,10 +1,12 @@
import { GraphQLResolveInfo } from 'graphql';
import { FieldMetadataInterface } from 'src/metadata/field-metadata/interfaces/field-metadata.interface';
import { ObjectMetadataInterface } from 'src/metadata/field-metadata/interfaces/object-metadata.interface';
export interface WorkspaceQueryRunnerOptions {
targetTableName: string;
workspaceId: string;
info: GraphQLResolveInfo;
fieldMetadataCollection: FieldMetadataInterface[];
objectMetadataCollection: ObjectMetadataInterface[];
}

View File

@ -64,11 +64,17 @@ export class WorkspaceQueryRunnerService {
): Promise<IConnection<Record> | undefined> {
try {
const { workspaceId, targetTableName } = options;
const start = performance.now();
const query = await this.workspaceQueryBuilderFactory.findMany(
args,
options,
);
const result = await this.execute(query, workspaceId);
const end = performance.now();
console.log(`query time: ${end - start} ms`);
return this.parseResult<IConnection<Record>>(result, targetTableName, '');
} catch (exception) {

View File

@ -30,6 +30,7 @@ export class CreateManyResolverFactory
workspaceId: internalContext.workspaceId,
info,
fieldMetadataCollection: internalContext.fieldMetadataCollection,
objectMetadataCollection: internalContext.objectMetadataCollection,
});
};
}

View File

@ -30,6 +30,7 @@ export class CreateOneResolverFactory
workspaceId: internalContext.workspaceId,
info,
fieldMetadataCollection: internalContext.fieldMetadataCollection,
objectMetadataCollection: internalContext.objectMetadataCollection,
});
};
}

View File

@ -30,6 +30,7 @@ export class DeleteManyResolverFactory
workspaceId: internalContext.workspaceId,
info,
fieldMetadataCollection: internalContext.fieldMetadataCollection,
objectMetadataCollection: internalContext.objectMetadataCollection,
});
};
}

View File

@ -30,6 +30,7 @@ export class DeleteOneResolverFactory
workspaceId: internalContext.workspaceId,
info,
fieldMetadataCollection: internalContext.fieldMetadataCollection,
objectMetadataCollection: internalContext.objectMetadataCollection,
});
};
}

View File

@ -36,6 +36,7 @@ export class ExecuteQuickActionOnOneResolverFactory
workspaceId: internalContext.workspaceId,
info,
fieldMetadataCollection: internalContext.fieldMetadataCollection,
objectMetadataCollection: internalContext.objectMetadataCollection,
});
};
}

View File

@ -30,6 +30,7 @@ export class FindManyResolverFactory
workspaceId: internalContext.workspaceId,
info,
fieldMetadataCollection: internalContext.fieldMetadataCollection,
objectMetadataCollection: internalContext.objectMetadataCollection,
});
};
}

View File

@ -30,6 +30,7 @@ export class FindOneResolverFactory
workspaceId: internalContext.workspaceId,
info,
fieldMetadataCollection: internalContext.fieldMetadataCollection,
objectMetadataCollection: internalContext.objectMetadataCollection,
});
};
}

View File

@ -30,6 +30,7 @@ export class UpdateManyResolverFactory
workspaceId: internalContext.workspaceId,
info,
fieldMetadataCollection: internalContext.fieldMetadataCollection,
objectMetadataCollection: internalContext.objectMetadataCollection,
});
};
}

View File

@ -30,6 +30,7 @@ export class UpdateOneResolverFactory
workspaceId: internalContext.workspaceId,
info,
fieldMetadataCollection: internalContext.fieldMetadataCollection,
objectMetadataCollection: internalContext.objectMetadataCollection,
});
};
}

View File

@ -81,6 +81,7 @@ export class WorkspaceResolverFactory {
workspaceId,
targetTableName: objectMetadata.targetTableName,
fieldMetadataCollection: objectMetadata.fields,
objectMetadataCollection: objectMetadataCollection,
});
}
@ -103,6 +104,7 @@ export class WorkspaceResolverFactory {
workspaceId,
targetTableName: objectMetadata.targetTableName,
fieldMetadataCollection: objectMetadata.fields,
objectMetadataCollection: objectMetadataCollection,
});
}
}

View File

@ -1,7 +1,9 @@
import { FieldMetadataInterface } from 'src/metadata/field-metadata/interfaces/field-metadata.interface';
import { ObjectMetadataInterface } from 'src/metadata/field-metadata/interfaces/object-metadata.interface';
export interface WorkspaceSchemaBuilderContext {
workspaceId: string;
targetTableName: string;
fieldMetadataCollection: FieldMetadataInterface[];
objectMetadataCollection: ObjectMetadataInterface[];
}