@@ -1313,6 +1313,157 @@ test('.setPriority() - execute a promise before planned', async t => {
1313
1313
t . deepEqual ( result , [ '🐌' , '🐢' , '🦆' ] ) ;
1314
1314
} ) ;
1315
1315
1316
+ test ( 'interval should be maintained when using await between adds (issue #182)' , async t => {
1317
+ const queue = new PQueue ( {
1318
+ intervalCap : 1 ,
1319
+ interval : 100 ,
1320
+ } ) ;
1321
+
1322
+ const timestamps : number [ ] = [ ] ;
1323
+
1324
+ // Add first 3 tasks without await
1325
+ queue . add ( ( ) => {
1326
+ timestamps . push ( Date . now ( ) ) ;
1327
+ return 'task1' ;
1328
+ } ) ;
1329
+ queue . add ( ( ) => {
1330
+ timestamps . push ( Date . now ( ) ) ;
1331
+ return 'task2' ;
1332
+ } ) ;
1333
+ queue . add ( ( ) => {
1334
+ timestamps . push ( Date . now ( ) ) ;
1335
+ return 'task3' ;
1336
+ } ) ;
1337
+
1338
+ // Add task 4 with await
1339
+ await queue . add ( ( ) => {
1340
+ timestamps . push ( Date . now ( ) ) ;
1341
+ return 'task4' ;
1342
+ } ) ;
1343
+
1344
+ // Add task 5 with await - this should still respect interval
1345
+ await queue . add ( ( ) => {
1346
+ timestamps . push ( Date . now ( ) ) ;
1347
+ return 'task5' ;
1348
+ } ) ;
1349
+
1350
+ // Add task 6 with await
1351
+ await queue . add ( ( ) => {
1352
+ timestamps . push ( Date . now ( ) ) ;
1353
+ return 'task6' ;
1354
+ } ) ;
1355
+
1356
+ // Check intervals between tasks
1357
+ for ( let i = 1 ; i < timestamps . length ; i ++ ) {
1358
+ const interval = timestamps [ i ] - timestamps [ i - 1 ] ;
1359
+ // Allow 10ms tolerance for timing
1360
+ t . true ( interval >= 90 , `Interval between task ${ i } and ${ i + 1 } was ${ interval } ms, expected >= 90ms` ) ;
1361
+ }
1362
+ } ) ;
1363
+
1364
+ test ( 'interval maintained when queue becomes empty multiple times' , async t => {
1365
+ const queue = new PQueue ( {
1366
+ intervalCap : 1 ,
1367
+ interval : 100 ,
1368
+ } ) ;
1369
+
1370
+ const timestamps : number [ ] = [ ] ;
1371
+
1372
+ // First batch
1373
+ await queue . add ( ( ) => {
1374
+ timestamps . push ( Date . now ( ) ) ;
1375
+ return 'task1' ;
1376
+ } ) ;
1377
+ await queue . add ( ( ) => {
1378
+ timestamps . push ( Date . now ( ) ) ;
1379
+ return 'task2' ;
1380
+ } ) ;
1381
+
1382
+ // Queue is empty, wait a bit
1383
+ await delay ( 50 ) ;
1384
+
1385
+ // Second batch - should still respect interval from task 2
1386
+ await queue . add ( ( ) => {
1387
+ timestamps . push ( Date . now ( ) ) ;
1388
+ return 'task3' ;
1389
+ } ) ;
1390
+ await queue . add ( ( ) => {
1391
+ timestamps . push ( Date . now ( ) ) ;
1392
+ return 'task4' ;
1393
+ } ) ;
1394
+
1395
+ // Check all intervals
1396
+ for ( let i = 1 ; i < timestamps . length ; i ++ ) {
1397
+ const interval = timestamps [ i ] - timestamps [ i - 1 ] ;
1398
+ t . true ( interval >= 90 , `Interval between task ${ i } and ${ i + 1 } was ${ interval } ms, expected >= 90ms` ) ;
1399
+ }
1400
+ } ) ;
1401
+
1402
+ test ( 'interval reset after long idle period' , async t => {
1403
+ const queue = new PQueue ( {
1404
+ intervalCap : 1 ,
1405
+ interval : 100 ,
1406
+ } ) ;
1407
+
1408
+ const timestamps : number [ ] = [ ] ;
1409
+
1410
+ // Run first task
1411
+ await queue . add ( ( ) => {
1412
+ timestamps . push ( Date . now ( ) ) ;
1413
+ return 'task1' ;
1414
+ } ) ;
1415
+
1416
+ // Wait much longer than interval
1417
+ await delay ( 250 ) ;
1418
+
1419
+ // This task should run immediately since enough time has passed
1420
+ await queue . add ( ( ) => {
1421
+ timestamps . push ( Date . now ( ) ) ;
1422
+ return 'task2' ;
1423
+ } ) ;
1424
+
1425
+ // But this one should wait for interval
1426
+ await queue . add ( ( ) => {
1427
+ timestamps . push ( Date . now ( ) ) ;
1428
+ return 'task3' ;
1429
+ } ) ;
1430
+
1431
+ const interval1to2 = timestamps [ 1 ] - timestamps [ 0 ] ;
1432
+ const interval2to3 = timestamps [ 2 ] - timestamps [ 1 ] ;
1433
+
1434
+ t . true ( interval1to2 >= 240 , `Task 2 ran after ${ interval1to2 } ms, expected >= 240ms` ) ;
1435
+ t . true ( interval2to3 >= 90 , `Task 3 should respect interval: ${ interval2to3 } ms` ) ;
1436
+ } ) ;
1437
+
1438
+ test ( 'interval with carryoverConcurrencyCount after queue empty' , async t => {
1439
+ const queue = new PQueue ( {
1440
+ intervalCap : 1 ,
1441
+ interval : 100 ,
1442
+ carryoverConcurrencyCount : true ,
1443
+ } ) ;
1444
+
1445
+ const timestamps : number [ ] = [ ] ;
1446
+
1447
+ // Run first task
1448
+ await queue . add ( ( ) => {
1449
+ timestamps . push ( Date . now ( ) ) ;
1450
+ return 'task1' ;
1451
+ } ) ;
1452
+
1453
+ // Queue becomes empty
1454
+ t . is ( queue . size , 0 ) ;
1455
+ t . is ( queue . pending , 0 ) ;
1456
+
1457
+ // Add new task - should respect interval
1458
+ await queue . add ( ( ) => {
1459
+ timestamps . push ( Date . now ( ) ) ;
1460
+ return 'task2' ;
1461
+ } ) ;
1462
+
1463
+ const interval = timestamps [ 1 ] - timestamps [ 0 ] ;
1464
+ t . true ( interval >= 90 , `Interval was ${ interval } ms, expected >= 90ms` ) ;
1465
+ } ) ;
1466
+
1316
1467
test ( '.setPriority() - execute a promise after planned' , async t => {
1317
1468
const result : string [ ] = [ ] ;
1318
1469
const queue = new PQueue ( { concurrency : 1 } ) ;
@@ -1453,3 +1604,24 @@ test('.setPriority() - execute a promise before planned - concurrency 3 and unsp
1453
1604
await queue . onIdle ( ) ;
1454
1605
t . deepEqual ( result , [ '🐌' , '🦆' , '🐢' , '🦀' , '⚡️' ] ) ;
1455
1606
} ) ;
1607
+
1608
+ test ( 'process exits cleanly after interval tasks complete' , async t => {
1609
+ const queue = new PQueue ( {
1610
+ concurrency : 100 ,
1611
+ intervalCap : 500 ,
1612
+ interval : 60 * 1000 ,
1613
+ } ) ;
1614
+
1615
+ // Execute tasks that complete quickly with long interval
1616
+ const tasks = [ ] ;
1617
+ for ( let i = 0 ; i < 4 ; i ++ ) {
1618
+ tasks . push ( queue . add ( ( ) => `result-${ i } ` ) ) ;
1619
+ }
1620
+
1621
+ await Promise . all ( tasks ) ;
1622
+ await queue . onIdle ( ) ;
1623
+
1624
+ // Test that no timers are hanging by checking process can exit naturally
1625
+ // This ensures both intervalId and timeoutId are cleared when idle
1626
+ t . pass ( ) ;
1627
+ } ) ;
0 commit comments