Skip to content

Commit

Permalink
Add processInChunks function to process files in chunks
Browse files Browse the repository at this point in the history
  • Loading branch information
richardrigutins authored Nov 9, 2023
1 parent b4bb2ab commit 31301c4
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 8 deletions.
34 changes: 33 additions & 1 deletion __tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import fs from 'fs';
import path from 'path';
import { getFiles, isValidEncoding, replaceTextInFile } from '../src/utils';
import {
getFiles,
isValidEncoding,
processInChunks,
replaceTextInFile,
} from '../src/utils';

describe('isValidEncoding', () => {
it('should return true for valid encodings', () => {
Expand Down Expand Up @@ -29,6 +34,33 @@ describe('getFiles', () => {
});
});

describe('processInChunks', () => {
it('should process an array in chunks', async () => {
const totalItems = 999;
const array = Array.from({ length: totalItems }, (_, i) => i);
const func = jest.fn(async (item: number) => {
item++;
});
const chunkSize = 100;

await processInChunks(array, func, chunkSize);

expect(func).toHaveBeenCalledTimes(totalItems);
});

it('should process an array with less items than chunk size', async () => {
const array = Array.from({ length: 50 }, (_, i) => i);
const func = jest.fn(async (item: number) => {
item++;
});
const chunkSize = 100;

await processInChunks(array, func, chunkSize);

expect(func).toHaveBeenCalledTimes(50);
});
});

describe('replaceTextInFile', () => {
const testFilePath = path.join(__dirname, 'test-file.txt');
const testFileContent = '{0}, world!';
Expand Down
36 changes: 32 additions & 4 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

16 changes: 14 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,29 @@ import {
Encoding,
getFiles,
isValidEncoding,
processInChunks,
replaceTextInFile,
} from './utils';

// Entry point for the action
async function run(): Promise<void> {
try {
// Get the input parameters
const filesPattern = getInput('files');
const searchText = getInput('search-text');
const replaceText = getInput('replacement-text');
const excludePattern = getInput('exclude');
const inputEncoding = getInput('encoding');

// Validate the encoding
if (!isValidEncoding(inputEncoding)) {
throw new Error(`Invalid encoding: ${inputEncoding}`);
}

// Get the file paths that match the files pattern and do not match the exclude pattern
const filePaths = await getFiles(filesPattern, excludePattern);

// If no file paths were found, log a warning and exit
if (filePaths.length === 0) {
warning(`No files found for the given pattern.`);
return;
Expand All @@ -28,14 +35,19 @@ async function run(): Promise<void> {
info(`Replacing "${searchText}" with "${replaceText}".`);

const encoding = inputEncoding as Encoding;
const promises: Promise<void>[] = filePaths.map(

// Process the file paths in chunks, replacing the search text with the replace text in each file
// This is done to avoid opening too many files at once
const chunkSize = 10;
await processInChunks(
filePaths,
async (filePath: string) => {
info(`Replacing text in file ${filePath}`);
await replaceTextInFile(filePath, searchText, replaceText, encoding);
},
chunkSize,
);

await Promise.all(promises);
info(`Done!`);
} catch (err) {
if (err instanceof Error) {
Expand Down
24 changes: 24 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,30 @@ export async function getFiles(
}
}

/**
* Processes an array in chunks, applying a given function to each item.
* @param array The array to process.
* @param func The function to apply to each item.
* @param chunkSize The number of items to process at a time.
* @returns A Promise that resolves when all items have been processed.
*/
export async function processInChunks<T>(
array: T[],
func: (item: T) => Promise<void>,
chunkSize: number,
): Promise<void> {
// Split the array into chunks
const chunks = Array(Math.ceil(array.length / chunkSize))
.fill(0)
.map((_, index) => index * chunkSize)
.map(begin => array.slice(begin, begin + chunkSize));

// Process each chunk
for (const chunk of chunks) {
await Promise.all(chunk.map(func));
}
}

/**
* Replaces all instances of the given text with the given value in the file.
* @param filePath The path of the file to modify.
Expand Down

0 comments on commit 31301c4

Please sign in to comment.