-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(runner): limit max concurrency without p-limit as a dependen…
…cy (#5980)
- Loading branch information
Showing
7 changed files
with
70 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,7 +43,6 @@ | |
}, | ||
"dependencies": { | ||
"@vitest/utils": "workspace:*", | ||
"p-limit": "^5.0.0", | ||
"pathe": "^1.1.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// A compact (code-wise, probably not memory-wise) singly linked list node. | ||
type QueueNode<T> = [value: T, next?: QueueNode<T>] | ||
|
||
/** | ||
* Return a function for running multiple async operations with limited concurrency. | ||
*/ | ||
export function limitConcurrency(concurrency = Infinity): <Args extends unknown[], T>(func: (...args: Args) => PromiseLike<T> | T, ...args: Args) => Promise<T> { | ||
// The number of currently active + pending tasks. | ||
let count = 0 | ||
|
||
// The head and tail of the pending task queue, built using a singly linked list. | ||
// Both head and tail are initially undefined, signifying an empty queue. | ||
// They both become undefined again whenever there are no pending tasks. | ||
let head: undefined | QueueNode<() => void> | ||
let tail: undefined | QueueNode<() => void> | ||
|
||
// A bookkeeping function executed whenever a task has been run to completion. | ||
const finish = () => { | ||
count-- | ||
|
||
// Check if there are further pending tasks in the queue. | ||
if (head) { | ||
// Allow the next pending task to run and pop it from the queue. | ||
head[0]() | ||
head = head[1] | ||
|
||
// The head may now be undefined if there are no further pending tasks. | ||
// In that case, set tail to undefined as well. | ||
tail = head && tail | ||
} | ||
} | ||
|
||
return (func, ...args) => { | ||
// Create a promise chain that: | ||
// 1. Waits for its turn in the task queue (if necessary). | ||
// 2. Runs the task. | ||
// 3. Allows the next pending task (if any) to run. | ||
return new Promise<void>((resolve) => { | ||
if (count++ < concurrency) { | ||
// No need to queue if fewer than maxConcurrency tasks are running. | ||
resolve() | ||
} | ||
else if (tail) { | ||
// There are pending tasks, so append to the queue. | ||
tail = tail[1] = [resolve] | ||
} | ||
else { | ||
// No other pending tasks, initialize the queue with a new tail and head. | ||
head = tail = [resolve] | ||
} | ||
}).then(() => { | ||
// Running func here ensures that even a non-thenable result or an | ||
// immediately thrown error gets wrapped into a Promise. | ||
return func(...args) | ||
}).finally(finish) | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters