Skip to content

Commit

Permalink
Loop with dynamic interval
Browse files Browse the repository at this point in the history
  • Loading branch information
jpuh committed Oct 29, 2024
1 parent 96b9123 commit 2b44aec
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 8 deletions.
12 changes: 9 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@ class ProcessManager {

async loop(fn, { interval = 0 } = {}) {
while (!this.terminating) {
await this.run(fn, { exit: false });
const result = await this.run(fn, { exit: false });

if (!this.terminating) {
await utils.timeout(interval);
await utils.timeout(result?.interval ?? interval);
}
}
}
Expand Down Expand Up @@ -148,13 +148,19 @@ class ProcessManager {

this.running.add(id);

const error = await utils.reflect(fn, args);
const result = await utils.reflect(fn, args);

this.running.delete(id);

const error = result instanceof Error ? result : undefined;

if (error || exit || this.terminating) {
await this.shutdown({ error });

return;
}

return result;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ module.exports.getDefaultLogger = function () {
};

/**
* Wraps a function and makes it return undefined on success or an error if it throws.
* Wraps a function and makes it return the function result on success or an error if it throws.
*/

module.exports.reflect = async function (thenable, args = []) {
try {
await thenable(...args);
return await thenable(...args);
} catch (error) {
return error;
}
Expand Down
27 changes: 27 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,33 @@ describe('ProcessManager', () => {
expect(fn).toHaveBeenCalledTimes(3);
});

test('handles dynamic interval', async () => {
const utils = require('../src/utils');

jest.spyOn(utils, 'timeout').mockImplementation(() => {});
const fn = jest.fn();

let i = 0;

await processManager.loop(
() => {
fn();

if (++i === 3) {
processManager.shutdown();
}

return i > 1 ? { interval: 1 } : undefined;
},
{ interval: 10 }
);

expect(fn).toHaveBeenCalledTimes(3);
expect(utils.timeout).toHaveBeenCalledTimes(2);
expect(utils.timeout).toHaveBeenNthCalledWith(1, 10);
expect(utils.timeout).toHaveBeenNthCalledWith(2, 1);
});

test('calls `shutdown` with error if an error is thrown while running the loop', async () => {
const error = new Error();

Expand Down
8 changes: 5 additions & 3 deletions test/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ describe('Utils', () => {
});

describe('reflect()', () => {
test('returns undefined if the passed function does not throw an error', async () => {
await expect(utils.reflect(() => 'foo')).resolves.toBeUndefined();
await expect(utils.reflect(() => Promise.resolve('foo'))).resolves.toBeUndefined();
test('returns the result of the the passed function', async () => {
await expect(utils.reflect(() => {})).resolves.toBeUndefined();
await expect(utils.reflect(() => 'foo')).resolves.toBe('foo');
await expect(utils.reflect(() => Promise.resolve('foo'))).resolves.toBe('foo');
await expect(utils.reflect(() => Promise.resolve({ foo: 1 }))).resolves.toEqual({ foo: 1 });
});

test('returns an error if the passed function throws an error', async () => {
Expand Down

0 comments on commit 2b44aec

Please sign in to comment.