Skip to content

Commit

Permalink
Add constrained promise parallelism
Browse files Browse the repository at this point in the history
Added a new method that runs at most a certain number of Promises at a time.
Allows a balance of resource usage safety and speed.

It's faster than sequential, but know we won't end up queuing so many
promises we end up with resource starvation.
I.e. restoring against 87 projects in the FAKE repo
  • Loading branch information
farlee2121 committed Jun 16, 2023
1 parent f392ed4 commit 3e791ea
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 3 deletions.
8 changes: 5 additions & 3 deletions src/Components/TestExplorer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -923,7 +923,9 @@ module Interactions =
let refreshTestList testItemFactory (rootTestCollection: TestItemCollection) tryGetLocation =
promise {

let! _ = ProjectExt.getAllWorkspaceProjects () |> Promise.executeForAll DotnetCli.restore
let! _ =
ProjectExt.getAllWorkspaceProjects ()
|> Promise.executeWithMaxParallel 4 DotnetCli.restore

let testProjectPaths =
Project.getInWorkspace ()
Expand All @@ -947,8 +949,8 @@ module Interactions =

let! _ =
testProjectPaths
|> List.map (fun projectPath -> DotnetCli.dotnetTest projectPath [| "--no-build" |])
|> Promise.Parallel
|> Promise.executeWithMaxParallel 2 (fun projectPath ->
DotnetCli.dotnetTest projectPath [| "--no-build" |])

let newTests =
TestDiscovery.discoverFromTrx testItemFactory tryGetLocation () |> ResizeArray
Expand Down
17 changes: 17 additions & 0 deletions src/Core/Utils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,23 @@ module Promise =
| [ x ] -> f x
| x :: tail -> tail |> List.fold (fun acc next -> acc |> Promise.bind (fun _ -> f next)) (f x)

let executeWithMaxParallel maxParallelCount (f: 'a -> JS.Promise<'b>) (items: 'a list) =
let initial = items |> List.take maxParallelCount

let mutable remaining =
Collections.Generic.Queue(collection = (items |> List.skip maxParallelCount))

let rec startNext promise =
promise
|> Promise.bind (fun _ ->
if remaining.Count = 0 then
promise
else
let next: 'a = remaining.Dequeue()
startNext (f next))

initial |> List.map (f >> startNext) |> Promise.all

module Event =

let invoke (listener: 'T -> _) (event: Fable.Import.VSCode.Vscode.Event<'T>) = event.Invoke(listener >> unbox)
Expand Down

0 comments on commit 3e791ea

Please sign in to comment.