Add sorter for distant tables (#5546)

As title
This commit is contained in:
Thomas Trompette 2024-05-23 22:36:50 +02:00 committed by GitHub
parent e00b19e4cc
commit fede721ba8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 147 additions and 73 deletions

View File

@ -10,7 +10,7 @@ import {
} from 'src/engine/metadata-modules/remote-server/remote-server.entity';
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
import { DistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table';
import { STRIPE_DISTANT_TABLES } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/util/stripe-distant-tables.util';
import { STRIPE_DISTANT_TABLES } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/utils/stripe-distant-tables.util';
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
@Injectable()

View File

@ -0,0 +1,53 @@
import { RemoteTableStatus } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto';
import { sortDistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/utils/sort-distant-tables.util';
const table1 = {
status: RemoteTableStatus.SYNCED,
name: 'table1',
};
const table2 = {
status: RemoteTableStatus.NOT_SYNCED,
name: 'table2',
};
describe('sortDistantTables', () => {
it('should return -1 when first param status is SYNCED and second param status is NOT_SYNCED', () => {
const result = sortDistantTables(table1, table2);
expect(result).toBe(-1);
});
it('should return 1 when first param status is NOT_SYNCED and second param status is SYNCED', () => {
const result = sortDistantTables(table2, table1);
expect(result).toBe(1);
});
it('should return -1 when same status and first param name is smaller than second param name', () => {
const result = sortDistantTables(
{ ...table1, status: RemoteTableStatus.NOT_SYNCED },
table2,
);
expect(result).toBe(-1);
});
it('should return 1 when same status and second param name is smaller than first param name', () => {
const result = sortDistantTables(table2, {
...table1,
status: RemoteTableStatus.NOT_SYNCED,
});
expect(result).toBe(1);
});
it('should be case insensitive', () => {
const result = sortDistantTables(
{ ...table1, name: 'table1', status: RemoteTableStatus.NOT_SYNCED },
{ ...table2, name: 'Table2' },
);
expect(result).toBe(-1);
});
});

View File

@ -0,0 +1,28 @@
import { RemoteTableStatus } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto';
export const sortDistantTables = (
table1: {
status: RemoteTableStatus;
name: string;
},
table2: {
status: RemoteTableStatus;
name: string;
},
) => {
if (
table1.status === RemoteTableStatus.SYNCED &&
table2.status === RemoteTableStatus.NOT_SYNCED
) {
return -1;
}
if (
table1.status === RemoteTableStatus.NOT_SYNCED &&
table2.status === RemoteTableStatus.SYNCED
) {
return 1;
}
return table1.name.toUpperCase() > table2.name.toUpperCase() ? 1 : -1;
};

View File

@ -2,10 +2,7 @@ import { Injectable } from '@nestjs/common';
import { getForeignTableColumnName as convertToForeignTableColumnName } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/utils/get-foreign-table-column-name.util';
import { DistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table';
import {
RemoteTableStatus,
DistantTableUpdate,
} from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto';
import { DistantTableUpdate } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto';
import { RemoteTableEntity } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.entity';
import { fetchTableColumns } from 'src/engine/metadata-modules/remote-server/remote-table/utils/fetch-table-columns.util';
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
@ -23,53 +20,6 @@ export class RemoteTableSchemaUpdateService {
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
) {}
public async getDistantTablesWithUpdates({
remoteServerSchema,
workspaceId,
remoteTables,
distantTables,
}: {
remoteServerSchema: string;
workspaceId: string;
remoteTables: RemoteTableEntity[];
distantTables: DistantTables;
}) {
const schemaPendingUpdates =
await this.getSchemaUpdatesBetweenForeignAndDistantTables({
workspaceId,
remoteTables,
distantTables,
});
const remoteTablesDistantNames = new Set(
remoteTables.map((remoteTable) => remoteTable.distantTableName),
);
const distantTablesWithUpdates = Object.keys(distantTables).map(
(tableName) => ({
name: tableName,
schema: remoteServerSchema,
status: remoteTablesDistantNames.has(tableName)
? RemoteTableStatus.SYNCED
: RemoteTableStatus.NOT_SYNCED,
schemaPendingUpdates: schemaPendingUpdates[tableName] || [],
}),
);
const deletedTables = Object.entries(schemaPendingUpdates)
.filter(([_tableName, updates]) =>
updates.includes(DistantTableUpdate.TABLE_DELETED),
)
.map(([tableName, updates]) => ({
name: tableName,
schema: remoteServerSchema,
status: RemoteTableStatus.SYNCED,
schemaPendingUpdates: updates,
}));
return [...distantTablesWithUpdates, ...deletedTables];
}
public computeForeignTableColumnsUpdates = (
foreignTableColumns: PostgresTableSchemaColumn[],
distantTableColumns: PostgresTableSchemaColumn[],
@ -94,7 +44,7 @@ export class RemoteTableSchemaUpdateService {
return [...columnsAddedUpdates, ...columnsDeletedUpdates];
};
private async getSchemaUpdatesBetweenForeignAndDistantTables({
public async getSchemaUpdatesBetweenForeignAndDistantTables({
workspaceId,
remoteTables,
distantTables,

View File

@ -19,7 +19,7 @@ export class RemoteTableResolver {
@Args('input') input: FindManyRemoteTablesInput,
@AuthWorkspace() { id: workspaceId }: Workspace,
) {
return this.remoteTableService.findDistantTablesWithStatusByServerId(
return this.remoteTableService.findDistantTablesWithStatus(
input.id,
workspaceId,
input.shouldFetchPendingSchemaUpdates,

View File

@ -9,7 +9,10 @@ import {
RemoteServerType,
RemoteServerEntity,
} from 'src/engine/metadata-modules/remote-server/remote-server.entity';
import { RemoteTableStatus } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto';
import {
DistantTableUpdate,
RemoteTableStatus,
} from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto';
import {
mapUdtNameToFieldType,
mapUdtNameToFieldSettings,
@ -31,6 +34,7 @@ import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-se
import { fetchTableColumns } from 'src/engine/metadata-modules/remote-server/remote-table/utils/fetch-table-columns.util';
import { ForeignTableService } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.service';
import { RemoteTableSchemaUpdateService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-schema-update/remote-table-schema-update.service';
import { sortDistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/utils/sort-distant-tables.util';
export class RemoteTableService {
private readonly logger = new Logger(RemoteTableService.name);
@ -52,7 +56,7 @@ export class RemoteTableService {
private readonly remoteTableSchemaUpdateService: RemoteTableSchemaUpdateService,
) {}
public async findDistantTablesWithStatusByServerId(
public async findDistantTablesWithStatus(
id: string,
workspaceId: string,
shouldFetchPendingSchemaUpdates?: boolean,
@ -82,26 +86,37 @@ export class RemoteTableService {
workspaceId,
);
if (currentRemoteTables.length === 0 || !shouldFetchPendingSchemaUpdates) {
const distantTablesWithStatus = Object.keys(distantTables).map(
(tableName) => ({
name: tableName,
schema: remoteServer.schema,
status: currentRemoteTableDistantNames.includes(tableName)
? RemoteTableStatus.SYNCED
: RemoteTableStatus.NOT_SYNCED,
}),
);
const distantTablesWithStatus = Object.keys(distantTables).map(
(tableName) => ({
name: tableName,
schema: remoteServer.schema,
status: currentRemoteTableDistantNames.includes(tableName)
? RemoteTableStatus.SYNCED
: RemoteTableStatus.NOT_SYNCED,
}),
);
return distantTablesWithStatus;
if (!shouldFetchPendingSchemaUpdates) {
return distantTablesWithStatus.sort(sortDistantTables);
}
return this.remoteTableSchemaUpdateService.getDistantTablesWithUpdates({
remoteServerSchema: remoteServer.schema,
workspaceId,
remoteTables: currentRemoteTables,
distantTables,
});
const schemaPendingUpdates =
await this.remoteTableSchemaUpdateService.getSchemaUpdatesBetweenForeignAndDistantTables(
{
workspaceId,
remoteTables: currentRemoteTables,
distantTables,
},
);
const distantTablesWithPendingUpdates =
this.getDistantTablesWithPendingUpdates(
schemaPendingUpdates,
distantTablesWithStatus,
remoteServer.schema,
);
return distantTablesWithPendingUpdates.sort(sortDistantTables);
}
public async findRemoteTablesByServerId({
@ -442,4 +457,32 @@ export class RemoteTableService {
}
}
}
private getDistantTablesWithPendingUpdates(
schemaPendingUpdates: { [tablename: string]: DistantTableUpdate[] },
distantTablesWithStatus: {
name: string;
schema: string;
status: RemoteTableStatus;
}[],
remoteServerSchema: string,
) {
const distantTablesWithUpdates = distantTablesWithStatus.map((table) => ({
...table,
schemaPendingUpdates: schemaPendingUpdates[table.name] || [],
}));
const deletedTables = Object.entries(schemaPendingUpdates)
.filter(([_tableName, updates]) =>
updates.includes(DistantTableUpdate.TABLE_DELETED),
)
.map(([tableName, updates]) => ({
name: tableName,
schema: remoteServerSchema,
status: RemoteTableStatus.SYNCED,
schemaPendingUpdates: updates,
}));
return [...distantTablesWithUpdates, ...deletedTables];
}
}