mirror of
https://github.com/dadosfera/maestro.git
synced 2026-10-30 21:59:07 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0eafa67e6f | ||
|
|
c3937472ec |
@@ -22,9 +22,6 @@ import {
|
||||
ConnectionTestListTablesRes,
|
||||
GetTableMetadataRes,
|
||||
GetTableMetadataReq,
|
||||
RefreshCatalogReq,
|
||||
RefreshCatalogRes,
|
||||
RefreshCatalogStatusReq,
|
||||
} from './dto/connection-test';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { Authenticated } from 'src/decorators/authentication.decorator';
|
||||
@@ -124,35 +121,4 @@ export class ConnectionTestController {
|
||||
user,
|
||||
);
|
||||
}
|
||||
|
||||
@Post('refresh-catalog')
|
||||
@ApiOkResponse({ type: RefreshCatalogRes })
|
||||
@HttpCode(HttpStatus.ACCEPTED)
|
||||
async refreshCatalog(
|
||||
@User() user: RequestUser,
|
||||
@Body(new ValidationPipe()) body: RefreshCatalogReq,
|
||||
) {
|
||||
this.logger.info('/connection-test/refresh-catalog', {
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
connection: body.connection_id,
|
||||
});
|
||||
return this.connectionTestService.refreshCatalog(body, user);
|
||||
}
|
||||
|
||||
@Post('refresh-catalog/status')
|
||||
@ApiOkResponse({ type: RefreshCatalogRes })
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async refreshCatalogStatus(
|
||||
@User() user: RequestUser,
|
||||
@Body(new ValidationPipe()) body: RefreshCatalogStatusReq,
|
||||
) {
|
||||
this.logger.info('/connection-test/refresh-catalog/status', {
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
connection: body.connection_id,
|
||||
session: body.session_id,
|
||||
});
|
||||
return this.connectionTestService.refreshCatalogStatus(body, user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import { ClientsModule } from '@nestjs/microservices';
|
||||
import { ConnectionTestClientConfiguration } from './connection-test-client.config';
|
||||
import { ConnectionModule } from '../connection/connection.module';
|
||||
import { ConnectionsApiModule } from '../connections-api/connections-api.module';
|
||||
import { PlatformApiModule } from '../platform-api/platform-api.module';
|
||||
const client = new ConnectionTestClientConfiguration();
|
||||
@Module({
|
||||
controllers: [ConnectionTestController],
|
||||
@@ -15,7 +14,6 @@ const client = new ConnectionTestClientConfiguration();
|
||||
ClientsModule.register([client.providerOptions]),
|
||||
ConnectionModule,
|
||||
ConnectionsApiModule,
|
||||
PlatformApiModule,
|
||||
],
|
||||
})
|
||||
export class ConnectionTestModule {}
|
||||
|
||||
@@ -16,7 +16,6 @@ describe('ConnectionTestService catalog cache', () => {
|
||||
const grpcClient = { getService: jest.fn().mockReturnValue({}) };
|
||||
const connectionsService = {};
|
||||
const connectionsApiService = { proxy: jest.fn() };
|
||||
const platformApiService = { proxy: jest.fn() };
|
||||
let service: ConnectionTestService;
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -25,7 +24,6 @@ describe('ConnectionTestService catalog cache', () => {
|
||||
grpcClient as any,
|
||||
connectionsService as any,
|
||||
connectionsApiService as any,
|
||||
platformApiService as any,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -108,98 +106,4 @@ describe('ConnectionTestService catalog cache', () => {
|
||||
user,
|
||||
);
|
||||
});
|
||||
|
||||
it('submits a catalog refresh without holding the request open', async () => {
|
||||
platformApiService.proxy.mockResolvedValue({
|
||||
session_id: 'session-id',
|
||||
date: '20260731',
|
||||
});
|
||||
|
||||
await expect(
|
||||
service.refreshCatalog(
|
||||
{ connection_id: 'config-id', plugin: 'postgresql' },
|
||||
user,
|
||||
),
|
||||
).resolves.toEqual({
|
||||
operation_result: true,
|
||||
status: 'PENDING',
|
||||
session_id: 'session-id',
|
||||
date: '20260731',
|
||||
});
|
||||
|
||||
expect(platformApiService.proxy).toHaveBeenCalledWith(
|
||||
'POST',
|
||||
'/connection_test',
|
||||
user,
|
||||
{
|
||||
customer_id: user.customer_name,
|
||||
plugin: 'postgresql',
|
||||
task: {
|
||||
task_type: 'refresh_catalog',
|
||||
connection: {
|
||||
provider: 'connection_manager',
|
||||
config_id: 'config-id',
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps polling without changing the catalog pointer while pending', async () => {
|
||||
platformApiService.proxy.mockResolvedValue({ status: 'PENDING' });
|
||||
|
||||
await expect(
|
||||
service.refreshCatalogStatus(
|
||||
{
|
||||
connection_id: 'config-id',
|
||||
plugin: 'postgresql',
|
||||
session_id: 'session-id',
|
||||
date: '20260731',
|
||||
},
|
||||
user,
|
||||
),
|
||||
).resolves.toEqual({
|
||||
operation_result: false,
|
||||
status: 'PENDING',
|
||||
session_id: 'session-id',
|
||||
date: '20260731',
|
||||
});
|
||||
|
||||
expect(connectionsApiService.proxy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('publishes the catalog pointer after the refresh finishes', async () => {
|
||||
platformApiService.proxy.mockResolvedValue({ status: 'DONE' });
|
||||
connectionsApiService.proxy.mockResolvedValue({
|
||||
last_catalog_refresh_status: 'SUCCESS',
|
||||
});
|
||||
|
||||
await expect(
|
||||
service.refreshCatalogStatus(
|
||||
{
|
||||
connection_id: 'config/id',
|
||||
plugin: 'postgresql',
|
||||
session_id: 'session-id',
|
||||
date: '20260731',
|
||||
},
|
||||
user,
|
||||
),
|
||||
).resolves.toEqual({
|
||||
operation_result: true,
|
||||
status: 'DONE',
|
||||
session_id: 'session-id',
|
||||
date: '20260731',
|
||||
});
|
||||
|
||||
expect(connectionsApiService.proxy).toHaveBeenCalledWith(
|
||||
'PUT',
|
||||
'/connection_config/config%2Fid/catalog_metadata',
|
||||
user,
|
||||
{
|
||||
last_catalog_refresh_status: 'SUCCESS',
|
||||
last_catalog_connection_test_date: '20260731',
|
||||
last_catalog_connection_test_session_id: 'session-id',
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import { ConnectionTest } from '@dadosfera/protospack-v2';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
@@ -13,9 +13,6 @@ import {
|
||||
ConnectionTestPingRes,
|
||||
GetTableMetadataReq,
|
||||
GetTableMetadataRes,
|
||||
RefreshCatalogReq,
|
||||
RefreshCatalogRes,
|
||||
RefreshCatalogStatusReq,
|
||||
} from './dto/connection-test';
|
||||
import { ConnectionClientService } from '../connection/client.service';
|
||||
import {
|
||||
@@ -25,7 +22,6 @@ import {
|
||||
import { RequestUser } from 'src/decorators/user.decorator';
|
||||
import { PackTheMetadata } from 'src/utils/PackTheMetadata';
|
||||
import { ConnectionsApiService } from '../connections-api/connections-api.service';
|
||||
import { PlatformApiService } from '../platform-api/platform-api.service';
|
||||
|
||||
@Injectable()
|
||||
export class ConnectionTestService {
|
||||
@@ -34,7 +30,6 @@ export class ConnectionTestService {
|
||||
@Inject('ConnectionTestGrpcClient') private readonly grpcClient: ClientGrpc,
|
||||
private connectionsService: ConnectionClientService,
|
||||
private connectionsApiService: ConnectionsApiService,
|
||||
private platformApiService: PlatformApiService,
|
||||
) {
|
||||
this.connectionTestReadClient =
|
||||
grpcClient.getService<ConnectionTest.ReadService.ConnectionTestReadServices>(
|
||||
@@ -209,82 +204,4 @@ export class ConnectionTestService {
|
||||
);
|
||||
return { operation_result: true, tables_metadata };
|
||||
}
|
||||
|
||||
async refreshCatalog(
|
||||
body: RefreshCatalogReq,
|
||||
user: RequestUser,
|
||||
): Promise<RefreshCatalogRes> {
|
||||
const task = await this.platformApiService.proxy(
|
||||
'POST',
|
||||
'/connection_test',
|
||||
user,
|
||||
{
|
||||
customer_id: user.customer_name,
|
||||
plugin: body.plugin,
|
||||
task: {
|
||||
task_type: 'refresh_catalog',
|
||||
connection: {
|
||||
provider: 'connection_manager',
|
||||
config_id: body.connection_id,
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (!task.session_id || !task.date) {
|
||||
throw new HttpException(
|
||||
'Platform API did not return a catalog refresh task identifier',
|
||||
HttpStatus.BAD_GATEWAY,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
operation_result: true,
|
||||
status: 'PENDING',
|
||||
session_id: task.session_id,
|
||||
date: task.date,
|
||||
};
|
||||
}
|
||||
|
||||
async refreshCatalogStatus(
|
||||
body: RefreshCatalogStatusReq,
|
||||
user: RequestUser,
|
||||
): Promise<RefreshCatalogRes> {
|
||||
const result = await this.platformApiService.proxy(
|
||||
'POST',
|
||||
'/connection_test/status',
|
||||
user,
|
||||
{
|
||||
session_id: body.session_id,
|
||||
date: body.date,
|
||||
},
|
||||
);
|
||||
|
||||
if (result.status === 'DONE') {
|
||||
await this.connectionsApiService.proxy(
|
||||
'PUT',
|
||||
`/connection_config/${encodeURIComponent(
|
||||
body.connection_id,
|
||||
)}/catalog_metadata`,
|
||||
user,
|
||||
{
|
||||
last_catalog_refresh_status: 'SUCCESS',
|
||||
last_catalog_connection_test_date: body.date,
|
||||
last_catalog_connection_test_session_id: body.session_id,
|
||||
},
|
||||
);
|
||||
} else if (result.status === 'ERROR' || result.status === 'EXPIRED') {
|
||||
throw new HttpException(
|
||||
`Catalog refresh finished with status ${result.status}`,
|
||||
HttpStatus.BAD_GATEWAY,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
operation_result: result.status === 'DONE',
|
||||
status: result.status,
|
||||
session_id: body.session_id,
|
||||
date: body.date,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ApiProperty, ApiPropertyOptional, OmitType } from '@nestjs/swagger';
|
||||
import { IsIn, IsString, IsOptional } from 'class-validator';
|
||||
import { IsString, IsOptional } from 'class-validator';
|
||||
import { DatabaseConnectionPropertiesDto } from 'src/modules/connection/dtos/connection';
|
||||
import { CreateConnectionDto } from 'src/modules/connection/dtos/connection';
|
||||
export class ColumnDto {
|
||||
@@ -133,37 +133,3 @@ export class GetTableMetadataRes {
|
||||
@ApiProperty({ type: [TableMetadataDto] })
|
||||
tables_metadata: TableMetadataDto[];
|
||||
}
|
||||
|
||||
export class RefreshCatalogReq {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
connection_id: string;
|
||||
|
||||
@ApiProperty({ enum: ['oracle', 'mysql', 'postgresql', 'sqlserver'] })
|
||||
@IsIn(['oracle', 'mysql', 'postgresql', 'sqlserver'])
|
||||
plugin: string;
|
||||
}
|
||||
|
||||
export class RefreshCatalogStatusReq extends RefreshCatalogReq {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
session_id: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
date: string;
|
||||
}
|
||||
|
||||
export class RefreshCatalogRes {
|
||||
@ApiProperty()
|
||||
operation_result: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
status: string;
|
||||
|
||||
@ApiProperty()
|
||||
session_id: string;
|
||||
|
||||
@ApiProperty()
|
||||
date: string;
|
||||
}
|
||||
|
||||
@@ -27,19 +27,9 @@ export class ConnectionsApiService {
|
||||
method: string,
|
||||
path: string,
|
||||
user: RequestUser,
|
||||
body?: any,
|
||||
query?: Record<string, string>,
|
||||
): Promise<any> {
|
||||
const baseUrl = CONNECTIONS_API_CONFIG.getUrl();
|
||||
const url = new URL(`${baseUrl}${path}`);
|
||||
|
||||
if (query) {
|
||||
Object.entries(query).forEach(([key, value]) => {
|
||||
if (value !== undefined && value !== null) {
|
||||
url.searchParams.set(key, String(value));
|
||||
}
|
||||
});
|
||||
}
|
||||
const headers: Record<string, string> = {
|
||||
host: url.hostname,
|
||||
'content-type': 'application/json',
|
||||
@@ -55,9 +45,8 @@ export class ConnectionsApiService {
|
||||
protocol: url.protocol,
|
||||
hostname: url.hostname,
|
||||
port: url.port ? parseInt(url.port, 10) : undefined,
|
||||
path: url.pathname + url.search,
|
||||
path: url.pathname,
|
||||
headers,
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -66,7 +55,6 @@ export class ConnectionsApiService {
|
||||
method: method as Method,
|
||||
url: url.href,
|
||||
headers: signedRequest.headers as Record<string, string>,
|
||||
data: body,
|
||||
timeout: CONNECTIONS_API_CONFIG.timeout,
|
||||
validateStatus: () => true,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user