Skip to content

Commit

Permalink
fix(output): Replace pMap with sequential processing in fileCollector…
Browse files Browse the repository at this point in the history
… to avoid file descriptor exhaustion
  • Loading branch information
yamadashy committed Aug 31, 2024
1 parent 8852074 commit 429f1af
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 19 deletions.
4 changes: 3 additions & 1 deletion src/cli/actions/defaultActionRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ export const runDefaultAction = async (
let packResult: PackResult;

try {
packResult = await pack(targetPath, config);
packResult = await pack(targetPath, config, (message) => {
spinner.update(message);
});
} catch (error) {
spinner.fail('Error during packing');
throw error;
Expand Down
2 changes: 2 additions & 0 deletions src/cli/actions/remoteActionRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export const runRemoteAction = async (repoUrl: string, options: CliOptions): Pro
spinner.start();
await cloneRepository(formattedUrl, tempDir);
spinner.succeed('Repository cloned successfully!');
logger.log('');

const result = await runDefaultAction(tempDir, tempDir, options);
await copyOutputToCurrentDirectory(tempDir, process.cwd(), result.config.output.filePath);
} finally {
Expand Down
5 changes: 5 additions & 0 deletions src/cli/cliSpinner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ class Spinner {
}, this.spinner.interval);
}

update(message: string): void {
this.message = message;
logUpdate(`${this.spinner.frames[this.currentFrame]} ${message}`);
}

stop(finalMessage: string): void {
if (this.interval) {
clearInterval(this.interval);
Expand Down
23 changes: 9 additions & 14 deletions src/core/file/fileCollector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,15 @@ import { getProcessConcurrency } from '../../shared/processConcurrency.js';
import type { RawFile } from './fileTypes.js';

export const collectFiles = async (filePaths: string[], rootDir: string): Promise<RawFile[]> => {
const rawFiles = await pMap(
filePaths,
async (filePath) => {
const fullPath = path.resolve(rootDir, filePath);
const content = await readRawFile(fullPath);
if (content) {
return { path: filePath, content };
}
return null;
},
{
concurrency: getProcessConcurrency(),
},
);
const rawFiles: RawFile[] = [];

for (const filePath of filePaths) {
const fullPath = path.resolve(rootDir, filePath);
const content = await readRawFile(fullPath);
if (content) {
rawFiles.push({ path: filePath, content });
}
}

return rawFiles.filter((file): file is RawFile => file != null);
};
Expand Down
16 changes: 14 additions & 2 deletions src/core/packager.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import * as fs from 'node:fs/promises';
import fs from 'node:fs/promises';
import path from 'node:path';
import pMap from 'p-map';
import type { RepopackConfigMerged } from '../config/configTypes.js';
import { logger } from '../shared/logger.js';
import { getProcessConcurrency } from '../shared/processConcurrency.js';
import type { RepopackProgressCallback } from '../shared/types.js';
import { collectFiles as defaultCollectFiles } from './file/fileCollector.js';
import { processFiles as defaultProcessFiles } from './file/fileProcessor.js';
import { searchFiles as defaultSearchFiles } from './file/fileSearcher.js';
Expand Down Expand Up @@ -34,6 +35,7 @@ export interface PackResult {
export const pack = async (
rootDir: string,
config: RepopackConfigMerged,
progressCallback: RepopackProgressCallback = () => {},
deps: PackDependencies = {
searchFiles: defaultSearchFiles,
collectFiles: defaultCollectFiles,
Expand All @@ -42,26 +44,35 @@ export const pack = async (
generateOutput: defaultGenerateOutput,
},
): Promise<PackResult> => {

// Get all file paths considering the config
progressCallback('Searching for files...');
const filePaths = await deps.searchFiles(rootDir, config);

// Collect raw files
progressCallback('Collecting files...');
const rawFiles = await deps.collectFiles(filePaths, rootDir);

// Perform security check and filter out suspicious files
progressCallback('Running security check...');
const suspiciousFilesResults = await deps.runSecurityCheck(rawFiles);
const safeRawFiles = rawFiles.filter(
(rawFile) => !suspiciousFilesResults.some((result) => result.filePath === rawFile.path),
);
const safeFilePaths = safeRawFiles.map((file) => file.path);

// Process files (remove comments, etc.)
progressCallback('Processing files...');
const processedFiles = await deps.processFiles(safeRawFiles, config);

// Generate output
const output = await deps.generateOutput(config, processedFiles, safeFilePaths);
progressCallback('Generating output...');
// const output = await deps.generateOutput(config, processedFiles, safeFilePaths);

const output = "a";

// Write output to file. path is relative to the cwd
progressCallback('Writing output file...');
const outputPath = path.resolve(config.cwd, config.output.filePath);
logger.trace(`Writing output to: ${outputPath}`);
await fs.writeFile(outputPath, output);
Expand All @@ -70,6 +81,7 @@ export const pack = async (
const tokenCounter = new TokenCounter();

// Metrics
progressCallback('Calculating metrics...');
const fileMetrics = await pMap(
processedFiles,
async (file) => {
Expand Down
1 change: 1 addition & 0 deletions src/shared/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type RepopackProgressCallback = (message: string) => void;
4 changes: 2 additions & 2 deletions tests/core/packager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('packager', () => {
test('pack should process files and generate output', async () => {
const mockConfig = createMockConfig();

const result = await pack('root', mockConfig, mockDeps);
const result = await pack('root', mockConfig, () => {}, mockDeps);

const file2Path = path.join('dir1', 'file2.txt');

Expand Down Expand Up @@ -79,7 +79,7 @@ describe('packager', () => {
},
]);

const result = await pack('root', mockConfig, mockDeps);
const result = await pack('root', mockConfig, () => {}, mockDeps);

expect(mockDeps.searchFiles).toHaveBeenCalledWith('root', mockConfig);
expect(mockDeps.processFiles).toHaveBeenCalledWith(
Expand Down

0 comments on commit 429f1af

Please sign in to comment.