1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-07-26 13:48:33 +02:00

refactor: move batch execute to oss (#9754)

This commit is contained in:
Mateusz Kwasniewski 2025-04-14 15:33:02 +02:00 committed by GitHub
parent e6d55ab17a
commit 9a25664a83
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 93 additions and 0 deletions

View File

@ -0,0 +1,76 @@
import { jest } from '@jest/globals';
import { batchExecute } from './batchExecute';
jest.useFakeTimers();
describe('batchExecute', () => {
let mockExecuteFn: jest.Mock;
beforeEach(() => {
mockExecuteFn = jest.fn();
});
afterEach(() => {
jest.clearAllTimers();
jest.clearAllMocks();
});
it('should process each item in batches of the specified size', async () => {
const items = Array.from({ length: 25 }, (_, i) => i);
const batchSize = 10;
const delayMs = 1000;
batchExecute(items, batchSize, delayMs, mockExecuteFn);
for (let i = 0; i < 2; i++) {
jest.advanceTimersByTime(delayMs);
await Promise.resolve();
}
expect(mockExecuteFn).toHaveBeenCalledTimes(items.length);
items.forEach((item, index) => {
expect(mockExecuteFn).toHaveBeenNthCalledWith(index + 1, item);
});
});
it('should delay between each batch', async () => {
const items = Array.from({ length: 15 }, (_, i) => i);
const batchSize = 5;
const delayMs = 1000;
batchExecute(items, batchSize, delayMs, mockExecuteFn);
expect(mockExecuteFn).toHaveBeenCalledTimes(5);
jest.advanceTimersByTime(delayMs);
await Promise.resolve();
expect(mockExecuteFn).toHaveBeenCalledTimes(10);
jest.advanceTimersByTime(delayMs);
await Promise.resolve();
expect(mockExecuteFn).toHaveBeenCalledTimes(15);
});
it('should handle empty items array without calling executeFn', async () => {
const items: number[] = [];
const batchSize = 10;
const delayMs = 1000;
await batchExecute(items, batchSize, delayMs, mockExecuteFn);
expect(mockExecuteFn).not.toHaveBeenCalled();
});
it('should handle a batch size larger than the number of items', async () => {
const items = [1, 2, 3];
const batchSize = 10;
const delayMs = 1000;
batchExecute(items, batchSize, delayMs, mockExecuteFn);
expect(mockExecuteFn).toHaveBeenCalledTimes(items.length);
items.forEach((item, index) => {
expect(mockExecuteFn).toHaveBeenNthCalledWith(index + 1, item);
});
});
});

View File

@ -0,0 +1,17 @@
export const batchExecute = async <T>(
items: T[],
batchSize: number,
delayMs: number,
executeFn: (item: T) => void,
) => {
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
// Execute function for each item in the batch sequentially, fire-and-forget
batch.forEach((item) => executeFn(item));
if (i + batchSize < items.length) {
await new Promise((resolve) => setTimeout(resolve, delayMs));
}
}
};