Skip to content

Commit 57d0a1a

Browse files
committed
Add timeoutRemaining to runningTasks
Fixes #247
1 parent fc4b736 commit 57d0a1a

3 files changed

Lines changed: 75 additions & 10 deletions

File tree

readme.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -476,14 +476,14 @@ setInterval(() => {
476476

477477
#### .runningTasks
478478

479-
The tasks currently being executed. Each task includes its `id`, `priority`, `startTime`, and `timeout` (if set).
479+
The tasks currently being executed. Each task includes its `id`, `priority`, `startTime`, `timeout` (if set), and `timeoutRemaining` (milliseconds until the task times out, or `undefined` if no timeout is set).
480480

481481
Returns an array of task info objects.
482482

483483
```js
484484
import PQueue from 'p-queue';
485485

486-
const queue = new PQueue({concurrency: 2});
486+
const queue = new PQueue({concurrency: 2, timeout: 10000});
487487

488488
// Add tasks with IDs for better debugging
489489
queue.add(() => fetchUser(123), {id: 'user-123'});
@@ -497,13 +497,15 @@ console.log(queue.runningTasks);
497497
id: 'user-123',
498498
priority: 0,
499499
startTime: 1759253001716,
500-
timeout: undefined
500+
timeout: 10000,
501+
timeoutRemaining: 9700
501502
},
502503
{
503504
id: 'posts-456',
504505
priority: 1,
505506
startTime: 1759253001916,
506-
timeout: undefined
507+
timeout: 10000,
508+
timeoutRemaining: 9900
507509
}
508510
]
509511
*/

source/index.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -921,14 +921,14 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
921921
}
922922

923923
/**
924-
The tasks currently being executed. Each task includes its `id`, `priority`, `startTime`, and `timeout` (if set).
924+
The tasks currently being executed. Each task includes its `id`, `priority`, `startTime`, `timeout` (if set), and `timeoutRemaining` (milliseconds until the task times out, or `undefined` if no timeout is set).
925925
926926
Returns an array of task info objects.
927927
928928
```js
929929
import PQueue from 'p-queue';
930930
931-
const queue = new PQueue({concurrency: 2});
931+
const queue = new PQueue({concurrency: 2, timeout: 10000});
932932
933933
// Add tasks with IDs for better debugging
934934
queue.add(() => fetchUser(123), {id: 'user-123'});
@@ -940,12 +940,14 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
940940
// id: 'user-123',
941941
// priority: 0,
942942
// startTime: 1759253001716,
943-
// timeout: undefined
943+
// timeout: 10000,
944+
// timeoutRemaining: 9700
944945
// }, {
945946
// id: 'posts-456',
946947
// priority: 1,
947948
// startTime: 1759253001916,
948-
// timeout: undefined
949+
// timeout: 10000,
950+
// timeoutRemaining: 9900
949951
// }]
950952
```
951953
*/
@@ -954,9 +956,13 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
954956
readonly priority: number;
955957
readonly startTime: number;
956958
readonly timeout?: number;
959+
readonly timeoutRemaining?: number;
957960
}> {
958961
// Return fresh array with fresh objects to prevent mutations
959-
return [...this.#runningTasks.values()].map(task => ({...task}));
962+
return [...this.#runningTasks.values()].map(task => ({
963+
...task,
964+
timeoutRemaining: task.timeout ? Math.max(0, task.startTime + task.timeout - Date.now()) : undefined,
965+
}));
960966
}
961967
}
962968

test/debug.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {test} from 'node:test';
2-
import assert from 'node:assert';
2+
import assert from 'node:assert/strict';
33
import delay from 'delay';
44
import PQueue from '../source/index.js';
55

@@ -122,6 +122,63 @@ test('runningTasks returns fresh arrays', async () => {
122122
await queue.onIdle();
123123
});
124124

125+
test('runningTasks includes timeoutRemaining for tasks with timeout', async () => {
126+
const queue = new PQueue({concurrency: 2, timeout: 5000});
127+
128+
queue.add(async () => delay(200), {id: 'with-timeout'});
129+
queue.add(async () => delay(200), {id: 'custom-timeout', timeout: 2000});
130+
131+
await delay(10);
132+
133+
const running = queue.runningTasks;
134+
const withTimeout = running.find(t => t.id === 'with-timeout');
135+
const customTimeout = running.find(t => t.id === 'custom-timeout');
136+
137+
assert.ok(withTimeout);
138+
assert.ok(typeof withTimeout.timeoutRemaining === 'number');
139+
assert.ok(withTimeout.timeoutRemaining! > 0);
140+
assert.ok(withTimeout.timeoutRemaining! <= 5000);
141+
142+
assert.ok(customTimeout);
143+
assert.ok(typeof customTimeout.timeoutRemaining === 'number');
144+
assert.ok(customTimeout.timeoutRemaining! > 0);
145+
assert.ok(customTimeout.timeoutRemaining! <= 2000);
146+
147+
await queue.onIdle();
148+
});
149+
150+
test('runningTasks timeoutRemaining is undefined when no timeout is set', async () => {
151+
const queue = new PQueue({concurrency: 1});
152+
153+
queue.add(async () => delay(100), {id: 'no-timeout'});
154+
155+
await delay(10);
156+
157+
const running = queue.runningTasks;
158+
assert.equal(running.length, 1);
159+
assert.equal(running[0].timeoutRemaining, undefined);
160+
161+
await queue.onIdle();
162+
});
163+
164+
test('runningTasks timeoutRemaining decreases over time', async () => {
165+
const queue = new PQueue({concurrency: 1, timeout: 5000});
166+
167+
queue.add(async () => delay(300), {id: 'task'});
168+
169+
await delay(10);
170+
171+
const remaining1 = queue.runningTasks[0].timeoutRemaining!;
172+
173+
await delay(100);
174+
175+
const remaining2 = queue.runningTasks[0].timeoutRemaining!;
176+
177+
assert.ok(remaining2 < remaining1, `Expected ${remaining2} < ${remaining1}`);
178+
179+
await queue.onIdle();
180+
});
181+
125182
test('runningTasks handles tasks without IDs', async () => {
126183
const queue = new PQueue({concurrency: 2});
127184

0 commit comments

Comments
 (0)