Skip to content

Commit f4e90e9

Browse files
author
Artem
committed
fix flaky test
1 parent a16796c commit f4e90e9

File tree

4 files changed

+38
-57
lines changed

4 files changed

+38
-57
lines changed

redisinsight/api/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"analytics-node": "^4.0.1",
6161
"axios": "^0.25.0",
6262
"body-parser": "^1.19.0",
63+
"busboy": "^1.6.0",
6364
"class-transformer": "^0.2.3",
6465
"class-validator": "^0.14.0",
6566
"connect-timeout": "^1.9.0",

redisinsight/api/src/modules/bulk-actions/bulk-import.controller.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import {
22
Body,
33
ClassSerializerInterceptor,
4-
Controller, HttpCode, Post,
4+
Controller, HttpCode, Post, Req,
55
UseInterceptors, UsePipes, ValidationPipe,
66
} from '@nestjs/common';
7+
import * as Busboy from 'busboy';
8+
import { Readable } from 'stream';
9+
import { Request } from 'express';
710
import {
811
ApiConsumes, ApiTags,
912
} from '@nestjs/swagger';
1013
import { ApiEndpoint } from 'src/decorators/api-endpoint.decorator';
11-
import { FormDataRequest } from 'nestjs-form-data';
1214
import { BulkImportService } from 'src/modules/bulk-actions/bulk-import.service';
13-
import { UploadImportFileDto } from 'src/modules/bulk-actions/dto/upload-import-file.dto';
1415
import { ClientMetadataParam } from 'src/common/decorators';
1516
import { ClientMetadata } from 'src/common/models';
1617
import { IBulkActionOverview } from 'src/modules/bulk-actions/interfaces/bulk-action-overview.interface';
@@ -26,7 +27,6 @@ export class BulkImportController {
2627
@Post('import')
2728
@ApiConsumes('multipart/form-data')
2829
@HttpCode(200)
29-
@FormDataRequest()
3030
@ApiEndpoint({
3131
description: 'Import data from file',
3232
responses: [
@@ -36,10 +36,21 @@ export class BulkImportController {
3636
],
3737
})
3838
async import(
39-
@Body() dto: UploadImportFileDto,
39+
@Req() req: Request,
4040
@ClientMetadataParam() clientMetadata: ClientMetadata,
4141
): Promise<IBulkActionOverview> {
42-
return this.service.import(clientMetadata, dto);
42+
return new Promise((res, rej) => {
43+
const busboy = Busboy({ headers: req.headers });
44+
45+
busboy.on(
46+
'file',
47+
(_fieldName: string, fileStream: Readable) => {
48+
this.service.import(clientMetadata, fileStream).then(res).catch(rej);
49+
},
50+
);
51+
52+
req.pipe(busboy);
53+
});
4354
}
4455

4556
@Post('import/tutorial-data')

redisinsight/api/src/modules/bulk-actions/bulk-import.service.ts

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { BadRequestException, Injectable, Logger } from '@nestjs/common';
44
import { Readable } from 'stream';
55
import * as readline from 'readline';
66
import { wrapHttpError } from 'src/common/utils';
7-
import { UploadImportFileDto } from 'src/modules/bulk-actions/dto/upload-import-file.dto';
87
import { DatabaseConnectionService } from 'src/modules/database/database-connection.service';
98
import { ClientMetadata } from 'src/common/models';
109
import { splitCliCommandLine } from 'src/utils/cli-helper';
@@ -14,7 +13,6 @@ import { BulkActionStatus, BulkActionType } from 'src/modules/bulk-actions/const
1413
import { BulkActionsAnalyticsService } from 'src/modules/bulk-actions/bulk-actions-analytics.service';
1514
import { UploadImportFileByPathDto } from 'src/modules/bulk-actions/dto/upload-import-file-by-path.dto';
1615
import config from 'src/utils/config';
17-
import { MemoryStoredFile } from 'nestjs-form-data';
1816

1917
const BATCH_LIMIT = 10_000;
2018
const PATH_CONFIG = config.get('dir_path');
@@ -63,9 +61,9 @@ export class BulkImportService {
6361

6462
/**
6563
* @param clientMetadata
66-
* @param dto
64+
* @param fileStream
6765
*/
68-
public async import(clientMetadata: ClientMetadata, dto: UploadImportFileDto): Promise<IBulkActionOverview> {
66+
public async import(clientMetadata: ClientMetadata, fileStream: Readable): Promise<IBulkActionOverview> {
6967
const startTime = Date.now();
7068
const result: IBulkActionOverview = {
7169
id: 'empty',
@@ -92,18 +90,20 @@ export class BulkImportService {
9290
try {
9391
client = await this.databaseConnectionService.createClient(clientMetadata);
9492

95-
const stream = Readable.from(dto.file.buffer);
9693
let batch = [];
9794

98-
const batchResults: Promise<BulkActionSummary>[] = [];
95+
const batchResults: BulkActionSummary[] = [];
96+
97+
try {
98+
const rl = readline.createInterface({
99+
input: fileStream,
100+
});
99101

100-
await new Promise((res) => {
101-
const rl = readline.createInterface(stream);
102-
rl.on('line', (line) => {
102+
for await (const line of rl) {
103103
try {
104104
const [command, ...args] = splitCliCommandLine((line.trim()));
105105
if (batch.length >= BATCH_LIMIT) {
106-
batchResults.push(this.executeBatch(client, batch));
106+
batchResults.push(await this.executeBatch(client, batch));
107107
batch = [];
108108
}
109109
if (command) {
@@ -112,20 +112,16 @@ export class BulkImportService {
112112
} catch (e) {
113113
parseErrors += 1;
114114
}
115-
});
116-
rl.on('error', (error) => {
117-
result.summary.errors.push(error);
118-
result.status = BulkActionStatus.Failed;
119-
this.analyticsService.sendActionFailed(result, error);
120-
res(null);
121-
});
122-
rl.on('close', () => {
123-
batchResults.push(this.executeBatch(client, batch));
124-
res(null);
125-
});
126-
});
115+
}
116+
} catch (e) {
117+
result.summary.errors.push(e);
118+
result.status = BulkActionStatus.Failed;
119+
this.analyticsService.sendActionFailed(result, e);
120+
}
121+
122+
batchResults.push(await this.executeBatch(client, batch));
127123

128-
(await Promise.all(batchResults)).forEach((batchResult) => {
124+
batchResults.forEach((batchResult) => {
129125
result.summary.processed += batchResult.getOverview().processed;
130126
result.summary.succeed += batchResult.getOverview().succeed;
131127
result.summary.failed += batchResult.getOverview().failed;
@@ -176,15 +172,7 @@ export class BulkImportService {
176172
throw new BadRequestException('Data file was not found');
177173
}
178174

179-
if ((await fs.stat(path))?.size > 100 * 1024 * 1024) {
180-
throw new BadRequestException('Maximum file size is 100MB');
181-
}
182-
183-
const buffer = await fs.readFile(path);
184-
185-
return this.import(clientMetadata, {
186-
file: { buffer } as MemoryStoredFile,
187-
});
175+
return this.import(clientMetadata, fs.createReadStream(path));
188176
} catch (e) {
189177
this.logger.error('Unable to process an import file path from tutorial', e);
190178
throw wrapHttpError(e);

redisinsight/api/src/modules/bulk-actions/dto/upload-import-file.dto.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)